Merge branch 'master' into search

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2022-05-02 13:43:24 +00:00
237 changed files with 3394 additions and 1014 deletions
+15 -45
View File
@@ -7,15 +7,14 @@ import (
"os"
"path"
"strconv"
"strings"
"github.com/cs3org/reva/v2/cmd/revad/runtime"
"github.com/gofrs/uuid"
"github.com/oklog/run"
"github.com/owncloud/ocis/extensions/frontend/pkg/config"
"github.com/owncloud/ocis/extensions/frontend/pkg/config/parser"
"github.com/owncloud/ocis/extensions/storage/pkg/server/debug"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/conversions"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/sync"
"github.com/owncloud/ocis/ocis-pkg/tracing"
@@ -28,11 +27,12 @@ func Frontend(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "frontend",
Usage: "start frontend service",
Before: func(c *cli.Context) error {
if err := loadUserAgent(c, cfg); err != nil {
return err
Before: func(ctx *cli.Context) error {
err := parser.ParseConfig(cfg)
if err != nil {
fmt.Printf("%v", err)
}
return nil
return err
},
Action: func(c *cli.Context) error {
logCfg := cfg.Logging
@@ -53,13 +53,6 @@ func Frontend(cfg *config.Config) *cli.Command {
uuid := uuid.Must(uuid.NewV4())
pidFile := path.Join(os.TempDir(), "revad-"+c.Command.Name+"-"+uuid.String()+".pid")
// pregenerate list of valid localhost ports for the desktop redirect_uri
// TODO use custom scheme like "owncloud://localhost/user/callback" tracked in
var desktopRedirectURIs [65535 - 1024]string
for port := 0; port < len(desktopRedirectURIs); port++ {
desktopRedirectURIs[port] = fmt.Sprintf("http://localhost:%d", (port + 1024))
}
archivers := []map[string]interface{}{
{
"enabled": true,
@@ -156,8 +149,8 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s
"tracing_service_name": c.Command.Name,
},
"shared": map[string]interface{}{
"jwt_secret": cfg.JWTSecret,
"gatewaysvc": cfg.GatewayEndpoint, // Todo or address?
"jwt_secret": cfg.TokenManager.JWTSecret,
"gatewaysvc": cfg.Reva.Address, // Todo or address?
"skip_user_groups_in_token": cfg.SkipUserGroupsInToken,
},
"http": map[string]interface{}{
@@ -194,13 +187,13 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s
"insecure": true,
},
"ocs": map[string]interface{}{
"storage_registry_svc": cfg.GatewayEndpoint,
"storage_registry_svc": cfg.Reva.Address,
"share_prefix": cfg.OCS.SharePrefix,
"home_namespace": cfg.OCS.HomeNamespace,
"resource_info_cache_ttl": cfg.OCS.ResourceInfoCacheTTL,
"prefix": cfg.OCS.Prefix,
"additional_info_attribute": cfg.OCS.AdditionalInfoAttribute,
"machine_auth_apikey": cfg.AuthMachine.APIKey,
"machine_auth_apikey": cfg.MachineAuthAPIKey,
"cache_warmup_driver": cfg.OCS.CacheWarmupDriver,
"cache_warmup_drivers": map[string]interface{}{
"cbox": map[string]interface{}{
@@ -210,7 +203,7 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s
"db_port": cfg.OCS.CacheWarmupDrivers.CBOX.DBPort,
"db_name": cfg.OCS.CacheWarmupDrivers.CBOX.DBName,
"namespace": cfg.OCS.CacheWarmupDrivers.CBOX.Namespace,
"gatewaysvc": cfg.GatewayEndpoint,
"gatewaysvc": cfg.Reva.Address,
},
},
"config": map[string]interface{}{
@@ -295,8 +288,10 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s
},
},
"spaces": map[string]interface{}{
"version": "0.0.1",
"enabled": cfg.EnableProjectSpaces,
"version": "0.0.1",
"enabled": cfg.EnableProjectSpaces || cfg.EnableShareJail,
"projects": cfg.EnableProjectSpaces,
"share_jail": cfg.EnableShareJail,
},
},
"version": map[string]interface{}{
@@ -313,31 +308,6 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s
}
}
// loadUserAgent reads the user-agent-whitelist-lock-in, since it is a string flag, and attempts to construct a map of
// "user-agent":"challenge" locks in for Reva.
// Modifies cfg. Spaces don't need to be trimmed as urfavecli takes care of it. User agents with spaces are valid. i.e:
// Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0
// This function works by relying in our format of specifying [user-agent:challenge] and the fact that the user agent
// might contain ":" (colon), so the original string is reversed, split in two parts, by the time it is split we
// have the indexes reversed and the tuple is in the format of [challenge:user-agent], then the same process is applied
// in reverse for each individual part
func loadUserAgent(c *cli.Context, cfg *config.Config) error {
cfg.Middleware.Auth.CredentialsByUserAgent = make(map[string]string)
locks := c.StringSlice("user-agent-whitelist-lock-in")
for _, v := range locks {
vv := conversions.Reverse(v)
parts := strings.SplitN(vv, ":", 2)
if len(parts) != 2 {
return fmt.Errorf("unexpected config value for user-agent lock-in: %v, expected format is user-agent:challenge", v)
}
cfg.Middleware.Auth.CredentialsByUserAgent[conversions.Reverse(parts[1])] = conversions.Reverse(parts[0])
}
return nil
}
// FrontendSutureService allows for the storage-frontend command to be embedded and supervised by a suture supervisor tree.
type FrontendSutureService struct {
cfg *config.Config
+30 -29
View File
@@ -8,31 +8,36 @@ type Config struct {
Tracing *Tracing `yaml:"tracing"`
Logging *Logging `yaml:"log"`
Debug Debug `yaml:"debug"`
Supervised bool
Supervised bool `yaml:"-"`
HTTP HTTPConfig `yaml:"http"`
// JWTSecret used to verify reva access token
JWTSecret string `yaml:"jwt_secret"`
GatewayEndpoint string
SkipUserGroupsInToken bool
EnableFavorites bool `yaml:"favorites"`
EnableProjectSpaces bool
TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"`
TokenManager *TokenManager `yaml:"token_manager"`
Reva *Reva `yaml:"reva"`
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;FRONTEND_MACHINE_AUTH_API_KEY"`
SkipUserGroupsInToken bool `yaml:"skip_users_groups_in_token"`
EnableFavorites bool `yaml:"favorites"`
EnableProjectSpaces bool `yaml:"enable_project_spaces" env:"FRONTEND_ENABLE_PROJECT_SPACES" desc:"Indicates to clients that project spaces are supposed to be made available."`
EnableShareJail bool `yaml:"enable_share_jail" env:"FRONTEND_ENABLE_SHARE_JAIL" desc:"Indicates to clients that the share jail is supposed to be used."`
UploadMaxChunkSize int `yaml:"upload_max_chunk_size"`
UploadHTTPMethodOverride string `yaml:"upload_http_method_override"`
DefaultUploadProtocol string `yaml:"default_upload_protocol"`
TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"`
PublicURL string `yaml:"public_url" env:"OCIS_URL;FRONTEND_PUBLIC_URL"`
Archiver Archiver
AppProvider AppProvider
DataGateway DataGateway
OCS OCS
AuthMachine AuthMachine
Checksums Checksums
PublicURL string `yaml:"public_url" env:"OCIS_URL;FRONTEND_PUBLIC_URL"`
Middleware Middleware
Archiver Archiver `yaml:"archiver"`
AppProvider AppProvider `yaml:"app_provider"`
DataGateway DataGateway `yaml:"data_gateway"`
OCS OCS `yaml:"ocs"`
Checksums Checksums `yaml:"checksums"`
Middleware Middleware `yaml:"middleware"`
}
type Tracing struct {
Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;FRONTEND_TRACING_ENABLED" desc:"Activates tracing."`
@@ -72,25 +77,25 @@ type Middleware struct {
// Auth configures reva http auth middleware.
type Auth struct {
CredentialsByUserAgent map[string]string `yaml:"credentials_by_user_agenr"`
CredentialsByUserAgent map[string]string `yaml:"credentials_by_user_agent"`
}
type Archiver struct {
MaxNumFiles int64 `yaml:"max_num_files"`
MaxSize int64 `yaml:"max_size"`
Prefix string
Insecure bool `env:"OCIS_INSECURE;FRONTEND_ARCHIVER_INSECURE"`
MaxNumFiles int64 `yaml:"max_num_files"`
MaxSize int64 `yaml:"max_size"`
Prefix string `yaml:"-"`
Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;FRONTEND_ARCHIVER_INSECURE"`
}
type AppProvider struct {
ExternalAddr string `yaml:"external_addr"`
Driver string `yaml:"driver"`
// WopiDriver WopiDriver `yaml:"wopi_driver"`
AppsURL string `yaml:"apps_url"`
OpenURL string `yaml:"open_url"`
NewURL string `yaml:"new_url"`
Prefix string
Insecure bool `env:"OCIS_INSECURE;FRONTEND_APPPROVIDER_INSECURE"`
AppsURL string `yaml:"-"`
OpenURL string `yaml:"-"`
NewURL string `yaml:"-"`
Prefix string `yaml:"-"`
Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;FRONTEND_APPPROVIDER_INSECURE"`
}
type DataGateway struct {
@@ -120,10 +125,6 @@ type CBOXDriver struct {
Namespace string
}
type AuthMachine struct {
APIKey string `env:"OCIS_MACHINE_AUTH_API_KEY"`
}
type Checksums struct {
SupportedTypes []string `yaml:"supported_types"`
PreferredUploadType string `yaml:"preferred_upload_type"`
@@ -6,9 +6,8 @@ import (
func FullDefaultConfig() *config.Config {
cfg := DefaultConfig()
EnsureDefaults(cfg)
Sanitize(cfg)
return cfg
}
@@ -28,15 +27,16 @@ func DefaultConfig() *config.Config {
Service: config.Service{
Name: "frontend",
},
GatewayEndpoint: "127.0.0.1:9142",
JWTSecret: "Pive-Fumkiu4",
Reva: &config.Reva{
Address: "127.0.0.1:9142",
},
PublicURL: "https://localhost:9200",
EnableFavorites: false,
EnableProjectSpaces: true,
EnableShareJail: true,
UploadMaxChunkSize: 1e+8,
UploadHTTPMethodOverride: "",
DefaultUploadProtocol: "tus",
TransferSecret: "replace-me-with-a-transfer-secret",
Checksums: config.Checksums{
SupportedTypes: []string{"sha1", "md5", "adler32"},
PreferredUploadType: "",
@@ -62,9 +62,6 @@ func DefaultConfig() *config.Config {
AdditionalInfoAttribute: "{{.Mail}}",
ResourceInfoCacheTTL: 0,
},
AuthMachine: config.AuthMachine{
APIKey: "change-me-please",
},
Middleware: config.Middleware{
Auth: config.Auth{
CredentialsByUserAgent: map[string]string{},
@@ -96,6 +93,31 @@ func EnsureDefaults(cfg *config.Config) {
} else if cfg.Tracing == nil {
cfg.Tracing = &config.Tracing{}
}
if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil {
cfg.Reva = &config.Reva{
Address: cfg.Commons.Reva.Address,
}
} else if cfg.Reva == nil {
cfg.Reva = &config.Reva{}
}
if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil {
cfg.TokenManager = &config.TokenManager{
JWTSecret: cfg.Commons.TokenManager.JWTSecret,
}
} else if cfg.TokenManager == nil {
cfg.TokenManager = &config.TokenManager{}
}
if cfg.TransferSecret == "" && cfg.Commons != nil && cfg.Commons.TransferSecret != "" {
cfg.TransferSecret = cfg.Commons.TransferSecret
}
if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" {
cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey
}
}
func Sanitize(cfg *config.Config) {
@@ -0,0 +1,50 @@
package parser
import (
"errors"
"github.com/owncloud/ocis/extensions/frontend/pkg/config"
"github.com/owncloud/ocis/extensions/frontend/pkg/config/defaults"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/shared"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
)
// ParseConfig loads configuration from known paths.
func ParseConfig(cfg *config.Config) error {
_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg)
if err != nil {
return err
}
defaults.EnsureDefaults(cfg)
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
// no environment variable set for this config is an expected "error"
if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) {
return err
}
}
defaults.Sanitize(cfg)
return Validate(cfg)
}
func Validate(cfg *config.Config) error {
if cfg.TokenManager.JWTSecret == "" {
return shared.MissingJWTTokenError(cfg.Service.Name)
}
if cfg.TransferSecret == "" {
return shared.MissingRevaTransferSecretError(cfg.Service.Name)
}
if cfg.MachineAuthAPIKey == "" {
return shared.MissingMachineAuthApiKeyError(cfg.Service.Name)
}
return nil
}
+11
View File
@@ -0,0 +1,11 @@
package config
// Reva defines all available REVA configuration.
type Reva struct {
Address string `yaml:"address" env:"REVA_GATEWAY"`
}
// TokenManager is the config for using the reva token manager
type TokenManager struct {
JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;FRONTEND_JWT_SECRET"`
}