mirror of
https://github.com/cs3org/reva.git
synced 2025-04-18 13:44:12 +03:00
Create home directory on login on configured home storage providers and other stuff (#469)
This commit is contained in:
parent
4c7513415e
commit
e6c824652a
1
.mailmap
1
.mailmap
@ -1,2 +1,3 @@
|
||||
Aritz Brosa <aritz.brosa.iartza@cern.ch> zazola <aritz.brosa@gmail.com>
|
||||
Giuseppe Lo Presti <giuseppe.lopresti@cern.ch> Giuseppe <giuseppe.lopresti@cern.ch>
|
||||
Michael D'Silva <michael.dsilva@aarnet.edu.au>
|
||||
|
@ -8,5 +8,6 @@
|
||||
- Ilja Neumann <ineumann@owncloud.com>
|
||||
- Jörn Friedrich Dreyer <jfd@butonic.de>
|
||||
- Michael D'Silva <md@aarnet.edu.au>
|
||||
- Michael D'Silva <michael.dsilva@aarnet.edu.au>
|
||||
- Mohitty <mohitt@iitk.ac.in>
|
||||
- Thomas Boerger <thomas@webhippie.de>
|
||||
|
@ -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) {
|
||||
|
@ -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}}"
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -1 +0,0 @@
|
||||
remote_theme: pmarsceill/just-the-docs
|
@ -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 <signal> -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.
|
||||
|
@ -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
|
||||
```
|
@ -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
|
||||
```
|
@ -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.
|
@ -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.
|
@ -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
|
@ -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.
|
@ -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
|
@ -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.
|
@ -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.
|
@ -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
|
||||
```
|
@ -1,3 +0,0 @@
|
||||
# HTTP Middleware: log
|
||||
|
||||
The logging middleware is always enabled with the highest priority. It will always receive requests first.
|
@ -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.
|
||||
|
@ -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.
|
@ -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
|
@ -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.
|
||||
|
@ -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.
|
@ -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"
|
||||
}
|
||||
```
|
@ -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).
|
@ -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"
|
@ -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"
|
@ -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"
|
@ -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"
|
||||
]
|
||||
}
|
@ -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 `<username>` 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/<username> 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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
[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
|
||||
# the context path wrapper reads tho username from the context and prefixes the relative storage path with it
|
||||
[grpc.services.storageprovider]
|
||||
driver = "owncloud"
|
||||
mount_path = "/home"
|
||||
mount_id = "123e4567-e89b-12d3-a456-426655440000"
|
||||
expose_data_server = true
|
||||
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]
|
||||
|
@ -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]
|
||||
|
@ -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 = ""
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
@ -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"
|
@ -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"]
|
||||
}
|
||||
]
|
@ -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"
|
||||
}
|
||||
]
|
3
go.mod
3
go.mod
@ -7,7 +7,7 @@ require (
|
||||
github.com/aws/aws-sdk-go v1.28.2
|
||||
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.9.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
|
||||
|
55
go.sum
55
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/aws/aws-sdk-go v1.28.2 h1:j5IXG9CdyLfcVfICqo1PXVv+rua+QQHbkXuvuU/JF+8=
|
||||
@ -43,23 +27,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=
|
||||
@ -71,8 +54,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=
|
||||
@ -83,7 +64,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=
|
||||
@ -100,14 +80,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=
|
||||
@ -127,11 +105,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=
|
||||
@ -139,7 +112,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=
|
||||
@ -170,7 +142,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=
|
||||
@ -194,7 +165,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=
|
||||
@ -210,7 +180,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=
|
||||
@ -236,10 +205,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=
|
||||
@ -250,7 +217,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=
|
||||
@ -259,9 +225,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=
|
||||
@ -276,13 +239,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=
|
||||
@ -292,14 +252,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=
|
||||
|
@ -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 == "" {
|
||||
conf.TokenManager = "jwt"
|
||||
}
|
||||
|
||||
if conf.TokenManager == "" {
|
||||
err := errors.New("auth: token manager is not configured for interceptor")
|
||||
return nil, err
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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")
|
||||
|
@ -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) {
|
||||
|
@ -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()),
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
55
pkg/sharedconf/sharedconf.go
Normal file
55
pkg/sharedconf/sharedconf.go
Normal file
@ -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
|
||||
}
|
64
pkg/sharedconf/sharedconf_test.go
Normal file
64
pkg/sharedconf/sharedconf_test.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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{}
|
||||
|
@ -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 /
|
||||
|
@ -35,73 +35,9 @@ func init() {
|
||||
registry.Register("static", New)
|
||||
}
|
||||
|
||||
type reg struct {
|
||||
rules map[string]string
|
||||
}
|
||||
|
||||
func (b *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, error) {
|
||||
providers := []*registrypb.ProviderInfo{}
|
||||
for k, v := range b.rules {
|
||||
providers = append(providers, ®istrypb.ProviderInfo{
|
||||
Address: v,
|
||||
ProviderPath: k,
|
||||
})
|
||||
}
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
return "", errors.New("static: home not found")
|
||||
}
|
||||
|
||||
func (b *reg) FindProvider(ctx context.Context, ref *provider.Reference) (*registrypb.ProviderInfo, error) {
|
||||
// find longest match
|
||||
var match string
|
||||
|
||||
// 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 {
|
||||
if strings.HasPrefix(fn, prefix) && len(prefix) > len(match) {
|
||||
match = prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if match != "" {
|
||||
return ®istrypb.ProviderInfo{
|
||||
ProviderPath: match,
|
||||
Address: b.rules[match],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// we try with id
|
||||
id := ref.GetId()
|
||||
if id == nil {
|
||||
return nil, errtypes.NotFound("storage provider not found for ref " + ref.String())
|
||||
}
|
||||
|
||||
for prefix := range b.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],
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return nil, errtypes.NotFound("storage provider not found for ref " + ref.String())
|
||||
}
|
||||
|
||||
type config struct {
|
||||
Rules map[string]string `mapstructure:"rules"`
|
||||
Rules map[string]string `mapstructure:"rules"`
|
||||
HomeProvider string `mapstructure:"home_provider"`
|
||||
}
|
||||
|
||||
func parseConfig(m map[string]interface{}) (*config, error) {
|
||||
@ -119,5 +55,73 @@ func New(m map[string]interface{}) (storage.Registry, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ®{rules: c.Rules}, nil
|
||||
return ®{c: c}, nil
|
||||
}
|
||||
|
||||
type reg struct {
|
||||
c *config
|
||||
}
|
||||
|
||||
func (b *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, error) {
|
||||
providers := []*registrypb.ProviderInfo{}
|
||||
for k, v := range b.c.Rules {
|
||||
providers = append(providers, ®istrypb.ProviderInfo{
|
||||
Address: v,
|
||||
ProviderPath: k,
|
||||
})
|
||||
}
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
// 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) (*registrypb.ProviderInfo, error) {
|
||||
for k, v := range b.c.Rules {
|
||||
if k == b.c.HomeProvider {
|
||||
return ®istrypb.ProviderInfo{
|
||||
ProviderPath: k,
|
||||
Address: v,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("static: home not found")
|
||||
}
|
||||
|
||||
func (b *reg) FindProvider(ctx context.Context, ref *provider.Reference) (*registrypb.ProviderInfo, error) {
|
||||
// find longest match
|
||||
var match string
|
||||
|
||||
// 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.c.Rules {
|
||||
if strings.HasPrefix(fn, prefix) && len(prefix) > len(match) {
|
||||
match = prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if match != "" {
|
||||
return ®istrypb.ProviderInfo{
|
||||
ProviderPath: match,
|
||||
Address: b.c.Rules[match],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// we try with id
|
||||
id := ref.GetId()
|
||||
if id == nil {
|
||||
return nil, errtypes.NotFound("storage provider not found for ref " + ref.String())
|
||||
}
|
||||
|
||||
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.c.Rules[prefix],
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return nil, errtypes.NotFound("storage provider not found for ref " + ref.String())
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user