Initial QSfera import
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
SHELL := bash
|
||||
NAME := ocm
|
||||
|
||||
ifneq (, $(shell command -v go 2> /dev/null)) # suppress `command not found warnings` for non go targets in CI
|
||||
include ../../.bingo/Variables.mk
|
||||
endif
|
||||
|
||||
include ../../.make/default.mk
|
||||
include ../../.make/go.mk
|
||||
include ../../.make/release.mk
|
||||
include ../../.make/docs.mk
|
||||
@@ -0,0 +1,132 @@
|
||||
# OCM
|
||||
|
||||
The `ocm` service provides federated sharing functionality based on the [sciencemesh](https://sciencemesh.io/) and [ocm](https://github.com/cs3org/OCM-API) HTTP APIs. Internally the `ocm` service consists of the following services and endpoints:
|
||||
|
||||
External HTTP APIs:
|
||||
* sciencemesh: serves the API for the invitation workflow
|
||||
* ocmd: serves the API for managing federated shares
|
||||
|
||||
Internal GRPC APIs:
|
||||
* ocmproviderauthorizer: manages the list of trusted providers and verifies requests
|
||||
* ocminvitemanager: manages the list and state of invite tokens
|
||||
* ocmshareprovider: manages ocm shares on the sharer
|
||||
* ocmcore: used for creating federated shares on the receiver side
|
||||
* authprovider: authenticates webdav requests using the ocm share tokens
|
||||
|
||||
## Enable OCM
|
||||
|
||||
To enable КуСфераMesh, you have to set the following environment variable.
|
||||
|
||||
```console
|
||||
OC_ENABLE_OCM=true
|
||||
```
|
||||
|
||||
## Trust Between Instances
|
||||
|
||||
The `ocm` services implements an invitation workflow which needs to be followed before creating federated shares. Invitations are limited to trusted instances, however.
|
||||
|
||||
The list of trusted instances is managed by the `ocmproviderauthorizer` service. The only supported backend currently is `json` which stores the list in a json file on disk. Note that the `ocmproviders.json` file, which holds that configuration, is expected to be located in the root of the КуСфера config directory if not otherwise defined. See the `OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE` envvar for more details.
|
||||
|
||||
When all instances of a federation should trust each other, an `ocmproviders.json` file like this can be used for all instances:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "КуСфера Test 1",
|
||||
"full_name": "КуСфера Test provider 1",
|
||||
"organization": "КуСфера One",
|
||||
"domain": "cloud1.qsfera.test",
|
||||
"homepage": "https://cloud1.qsfera.test",
|
||||
"description": "First КуСфера Example cloud storage",
|
||||
"services": [
|
||||
{
|
||||
"endpoint": {
|
||||
"type": {
|
||||
"name": "OCM",
|
||||
"description": "cloud1.qsfera.test Open Cloud Mesh API"
|
||||
},
|
||||
"name": "cloud1.qsfera.test - OCM API",
|
||||
"path": "https://cloud1.qsfera.test/ocm/",
|
||||
"is_monitored": true
|
||||
},
|
||||
"api_version": "0.0.1",
|
||||
"host": "http://cloud1.qsfera.test"
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"type": {
|
||||
"name": "Webdav",
|
||||
"description": "cloud1.qsfera.test Webdav API"
|
||||
},
|
||||
"name": "cloud1.qsfera.test Example - Webdav API",
|
||||
"path": "https://cloud1.qsfera.test/dav/",
|
||||
"is_monitored": true
|
||||
},
|
||||
"api_version": "0.0.1",
|
||||
"host": "https://cloud1.qsfera.test/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "КуСфера Test 2",
|
||||
"full_name": "КуСфера Test provider 2",
|
||||
"organization": "КуСфера Two",
|
||||
"domain": "cloud2.qsfera.test",
|
||||
"homepage": "https://cloud2.qsfera.test",
|
||||
"description": "Second КуСфера Example cloud storage",
|
||||
"services": [
|
||||
{
|
||||
"endpoint": {
|
||||
"type": {
|
||||
"name": "OCM",
|
||||
"description": "cloud2.qsfera.test Open Cloud Mesh API"
|
||||
},
|
||||
"name": "cloud2.qsfera.test - OCM API",
|
||||
"path": "https://cloud2.qsfera.test/ocm/",
|
||||
"is_monitored": true
|
||||
},
|
||||
"api_version": "0.0.1",
|
||||
"host": "http://cloud2.qsfera.test"
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"type": {
|
||||
"name": "Webdav",
|
||||
"description": "cloud2.qsfera.test Webdav API"
|
||||
},
|
||||
"name": "cloud2.qsfera.test Example - Webdav API",
|
||||
"path": "https://cloud2.qsfera.test/dav/",
|
||||
"is_monitored": true
|
||||
},
|
||||
"api_version": "0.0.1",
|
||||
"host": "https://cloud2.qsfera.test/"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
:::info
|
||||
Note: the `domain` must not contain the protocol as it has to match the [GOCDB site object domain](https://developer.sciencemesh.io/docs/technical-documentation/central-database/#site-object).
|
||||
:::
|
||||
|
||||
The above federation consists of two instances: `cloud1.qsfera.test` and `cloud2.qsfera.test` that can use the Invitation workflow described below to generate, send and accept invitations.
|
||||
|
||||
## Invitation Workflow
|
||||
|
||||
Before sharing a resource with a remote user this user has to be invited by the sharer.
|
||||
|
||||
In order to do so a POST request is sent to the `generate-invite` endpoint of the sciencemesh API. The generated token is passed on to the receiver, who will then use the `accept-invite` endpoint to accept the invitation. As a result remote users will be added to the `ocminvitemanager` on both sides. See [invitation flow](invitation-flow) for the according sequence diagram.
|
||||
|
||||
The data backend of the `ocminvitemanager` is configurable. The only supported backend currently is `json` which stores the data in a json file on disk.
|
||||
|
||||
## Creating Shares
|
||||
|
||||
:::info
|
||||
The below info is outdated as we allow creating federated shares using the graph API. Clients can now discover the available sharing roles and invite federated users using the graph API.
|
||||
:::
|
||||
|
||||
OCM Shares are currently created using the ocs API, just like regular shares. The difference is the share type, which is 6 (ShareTypeFederatedCloudShare) in this case, and a few additional parameters required for identifying the remote user.
|
||||
|
||||
See [Create share flow](create-share-flow) for the according sequence diagram.
|
||||
|
||||
The data backends of the `ocmshareprovider` and `ocmcore` services are configurable. The only supported backend currently is `json` which stores the data in a json file on disk.
|
||||
@@ -0,0 +1,19 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Health is the entrypoint for the health command.
|
||||
func Health(cfg *config.Config) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "health",
|
||||
Short: "Check health status",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// Not implemented
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/qsfera/server/pkg/clihelper"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// GetCommands provides all commands for this service
|
||||
func GetCommands(cfg *config.Config) []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
// start this service
|
||||
Server(cfg),
|
||||
|
||||
// interaction with this service
|
||||
|
||||
// infos about this service
|
||||
Health(cfg),
|
||||
Version(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
// Execute is the entry point for the ocm command.
|
||||
func Execute(cfg *config.Config) error {
|
||||
app := clihelper.DefaultApp(&cobra.Command{
|
||||
Use: "ocm",
|
||||
Short: "starts ocm service",
|
||||
})
|
||||
app.AddCommand(GetCommands(cfg)...)
|
||||
app.SetArgs(os.Args[1:])
|
||||
|
||||
return app.ExecuteContext(cfg.Context)
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/signal"
|
||||
|
||||
"github.com/qsfera/server/pkg/config/configlog"
|
||||
"github.com/qsfera/server/pkg/log"
|
||||
"github.com/qsfera/server/pkg/registry"
|
||||
"github.com/qsfera/server/pkg/runner"
|
||||
"github.com/qsfera/server/pkg/tracing"
|
||||
"github.com/qsfera/server/pkg/version"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config/parser"
|
||||
"github.com/qsfera/server/services/ocm/pkg/revaconfig"
|
||||
"github.com/qsfera/server/services/ocm/pkg/server/debug"
|
||||
"github.com/opencloud-eu/reva/v2/cmd/revad/runtime"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Server is the entrypoint for the server command.
|
||||
func Server(cfg *config.Config) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "server",
|
||||
Short: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return configlog.ReturnFatal(parser.ParseConfig(cfg))
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
logger := log.Configure(cfg.Service.Name, cfg.Commons, cfg.LogLevel)
|
||||
traceProvider, err := tracing.GetTraceProvider(cmd.Context(), cfg.Commons.TracesExporter, cfg.Service.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cancel context.CancelFunc
|
||||
if cfg.Context == nil {
|
||||
cfg.Context, cancel = signal.NotifyContext(context.Background(), runner.StopSignals...)
|
||||
defer cancel()
|
||||
}
|
||||
ctx := cfg.Context
|
||||
|
||||
gr := runner.NewGroup()
|
||||
|
||||
{
|
||||
// run the appropriate reva servers based on the config
|
||||
rCfg := revaconfig.OCMConfigFromStruct(cfg, logger)
|
||||
if rServer := runtime.NewDrivenHTTPServerWithOptions(rCfg,
|
||||
runtime.WithLogger(&logger.Logger),
|
||||
runtime.WithRegistry(registry.GetRegistry()),
|
||||
runtime.WithTraceProvider(traceProvider),
|
||||
); rServer != nil {
|
||||
gr.Add(runner.NewRevaServiceRunner(cfg.Service.Name+".rhttp", rServer))
|
||||
}
|
||||
if rServer := runtime.NewDrivenGRPCServerWithOptions(rCfg,
|
||||
runtime.WithLogger(&logger.Logger),
|
||||
runtime.WithRegistry(registry.GetRegistry()),
|
||||
runtime.WithTraceProvider(traceProvider),
|
||||
); rServer != nil {
|
||||
gr.Add(runner.NewRevaServiceRunner(cfg.Service.Name+".rgrpc", rServer))
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
debugServer, err := debug.Server(
|
||||
debug.Logger(logger),
|
||||
debug.Context(ctx),
|
||||
debug.Config(cfg),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Info().Err(err).Str("server", "debug").Msg("Failed to initialize server")
|
||||
return err
|
||||
}
|
||||
|
||||
gr.Add(runner.NewGolangHttpServerRunner(cfg.Service.Name+".debug", debugServer))
|
||||
}
|
||||
|
||||
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, cfg.GRPC.Protocol, cfg.GRPC.Addr, version.GetString())
|
||||
if err := registry.RegisterService(ctx, logger, grpcSvc, cfg.Debug.Addr); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to register the grpc service")
|
||||
}
|
||||
|
||||
httpSvc := registry.BuildHTTPService(cfg.HTTP.Namespace+"."+cfg.Service.Name, cfg.HTTP.Addr, version.GetString())
|
||||
if err := registry.RegisterService(ctx, logger, httpSvc, cfg.Debug.Addr); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to register the http service")
|
||||
}
|
||||
|
||||
grResults := gr.Run(ctx)
|
||||
|
||||
// return the first non-nil error found in the results
|
||||
for _, grResult := range grResults {
|
||||
if grResult.RunnerError != nil {
|
||||
return grResult.RunnerError
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Version prints the service versions of all running instances.
|
||||
func Version(cfg *config.Config) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "print the version of this binary and the running service instances",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// not implemented
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go-micro.dev/v4/client"
|
||||
|
||||
"github.com/qsfera/server/pkg/shared"
|
||||
)
|
||||
|
||||
// Config combines all available configuration parts.
|
||||
type Config struct {
|
||||
Commons *shared.Commons `yaml:"-"` // don't use this directly as configuration for a service
|
||||
|
||||
Service Service `yaml:"-"`
|
||||
|
||||
LogLevel string `yaml:"loglevel" env:"OC_LOG_LEVEL;OCM_LOG_LEVEL" desc:"The log level. Valid values are: 'panic', 'fatal', 'error', 'warn', 'info', 'debug', 'trace'." introductionVersion:"1.0.0"`
|
||||
Debug Debug `yaml:"debug"`
|
||||
|
||||
HTTP HTTPConfig `yaml:"http"`
|
||||
Middleware Middleware `yaml:"middleware"`
|
||||
GRPC GRPCConfig `yaml:"grpc"`
|
||||
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
|
||||
GrpcClient client.Client `yaml:"-"`
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
Events Events `yaml:"-"`
|
||||
|
||||
TokenManager *TokenManager `yaml:"token_manager"`
|
||||
Reva *shared.Reva `yaml:"reva"`
|
||||
OCMD OCMD `yaml:"ocmd"`
|
||||
ScienceMesh ScienceMesh `yaml:"sciencemesh"`
|
||||
OCMInviteManager OCMInviteManager `yaml:"ocm_invite_manager"`
|
||||
OCMProviderAuthorizerDriver string `yaml:"ocm_provider_authorizer_driver" env:"SHARING_OCM_PROVIDER_AUTHORIZER_DRIVER" desc:"Driver to be used to persist ocm invites. Supported value is only 'json'." introductionVersion:"1.0.0"`
|
||||
OCMProviderAuthorizerDrivers OCMProviderAuthorizerDrivers `yaml:"ocm_provider_authorizer_drivers"`
|
||||
OCMShareProvider OCMShareProvider `yaml:"ocm_share_provider"`
|
||||
OCMCore OCMCore `yaml:"ocm_core"`
|
||||
OCMStorageProvider OCMStorageProvider `yaml:"ocm_storage_provider"`
|
||||
|
||||
Context context.Context `yaml:"-"`
|
||||
}
|
||||
|
||||
// HTTPConfig defines the available http configuration.
|
||||
type HTTPConfig struct {
|
||||
Addr string `yaml:"addr" env:"OCM_HTTP_ADDR" desc:"The bind address of the HTTP service." introductionVersion:"1.0.0"`
|
||||
Namespace string `yaml:"-"`
|
||||
Protocol string `yaml:"protocol" env:"OCM_HTTP_PROTOCOL" desc:"The transport protocol of the HTTP service." introductionVersion:"1.0.0"`
|
||||
Prefix string `yaml:"prefix" env:"OCM_HTTP_PREFIX" desc:"The path prefix where OCM can be accessed (defaults to /)." introductionVersion:"1.0.0"`
|
||||
CORS CORS `yaml:"cors"`
|
||||
}
|
||||
|
||||
// Middleware configures reva middlewares.
|
||||
type Middleware struct {
|
||||
Auth Auth `yaml:"auth"`
|
||||
}
|
||||
|
||||
// Auth configures reva http auth middleware.
|
||||
type Auth struct {
|
||||
CredentialsByUserAgent map[string]string `yaml:"credentials_by_user_agent"`
|
||||
}
|
||||
|
||||
// ServiceAccount is the configuration for the used service account
|
||||
type ServiceAccount struct {
|
||||
ID string `yaml:"service_account_id" env:"OC_SERVICE_ACCOUNT_ID;OCM_SERVICE_ACCOUNT_ID" desc:"The ID of the service account the service should use. See the 'auth-service' service description for more details." introductionVersion:"1.0.0"`
|
||||
Secret string `yaml:"service_account_secret" env:"OC_SERVICE_ACCOUNT_SECRET;OCM_SERVICE_ACCOUNT_SECRET" desc:"The service account secret." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
// CORS defines the available cors configuration.
|
||||
type CORS struct {
|
||||
AllowedOrigins []string `yaml:"allow_origins" env:"OC_CORS_ALLOW_ORIGINS;OCM_CORS_ALLOW_ORIGINS" desc:"A list of allowed CORS origins. See following chapter for more details: *Access-Control-Allow-Origin* at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
AllowedMethods []string `yaml:"allow_methods" env:"OC_CORS_ALLOW_METHODS;OCM_CORS_ALLOW_METHODS" desc:"A list of allowed CORS methods. See following chapter for more details: *Access-Control-Request-Method* at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
AllowedHeaders []string `yaml:"allow_headers" env:"OC_CORS_ALLOW_HEADERS;OCM_CORS_ALLOW_HEADERS" desc:"A list of allowed CORS headers. See following chapter for more details: *Access-Control-Request-Headers* at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers. See the Environment Variable Types description for more details." introductionVersion:"1.0.0"`
|
||||
AllowCredentials bool `yaml:"allow_credentials" env:"OC_CORS_ALLOW_CREDENTIALS;OCM_CORS_ALLOW_CREDENTIALS" desc:"Allow credentials for CORS.See following chapter for more details: *Access-Control-Allow-Credentials* at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
// GRPCConfig defines the available grpc configuration.
|
||||
type GRPCConfig struct {
|
||||
Addr string `yaml:"addr" env:"OCM_GRPC_ADDR" desc:"The bind address of the GRPC service." introductionVersion:"1.0.0"`
|
||||
Namespace string `yaml:"-"`
|
||||
TLS *shared.GRPCServiceTLS `yaml:"tls"`
|
||||
Protocol string `yaml:"protocol" env:"OC_GRPC_PROTOCOL;OCM_GRPC_PROTOCOL" desc:"The transport protocol of the GRPC service." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type ScienceMesh struct {
|
||||
Prefix string `yaml:"prefix" env:"OCM_SCIENCEMESH_PREFIX" desc:"URL path prefix for the ScienceMesh service. Note that the string must not start with '/'." introductionVersion:"1.0.0"`
|
||||
MeshDirectoryURL string `yaml:"science_mesh_directory_url" env:"OCM_MESH_DIRECTORY_URL" desc:"URL of the mesh directory service." introductionVersion:"1.0.0"`
|
||||
DirectoryServiceURLs string `yaml:"directory_service_urls" env:"OCM_DIRECTORY_SERVICE_URLS" desc:"Space delimited URLs of the directory services." introductionVersion:"3.5.0"`
|
||||
InviteAcceptDialog string `yaml:"invite_accept_dialog" env:"OCM_INVITE_ACCEPT_DIALOG" desc:"/open-cloud-mesh/accept-invite;The frontend URL where to land when receiving an invitation" introductionVersion:"3.5.0"`
|
||||
OCMClientInsecure bool `yaml:"ocm_client_insecure" env:"OC_INSECURE;OCM_CLIENT_INSECURE" desc:"Dev-only. Disable TLS verification for the OCM discovery client (directory fetch and provider discovery). Does not affect OCM invite manager, storage provider, or share provider. Do not set in production." introductionVersion:"6.0.0"`
|
||||
}
|
||||
|
||||
type OCMD struct {
|
||||
Prefix string `yaml:"prefix" env:"OCM_OCMD_PREFIX" desc:"URL path prefix for the OCMD service. Note that the string must not start with '/'." introductionVersion:"1.0.0"`
|
||||
ExposeRecipientDisplayName bool `yaml:"expose_recipient_display_name" env:"OCM_OCMD_EXPOSE_RECIPIENT_DISPLAY_NAME" desc:"Expose the display name of OCM share recipients." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMInviteManager struct {
|
||||
Driver string `yaml:"driver" env:"OCM_OCM_INVITE_MANAGER_DRIVER" desc:"Driver to be used to persist OCM invites. Supported value is only 'json'." introductionVersion:"1.0.0"`
|
||||
Drivers OCMInviteManagerDrivers `yaml:"drivers"`
|
||||
TokenExpiration time.Duration `yaml:"token_expiration" env:"OCM_OCM_INVITE_MANAGER_TOKEN_EXPIRATION" desc:"Expiry duration for invite tokens." introductionVersion:"1.0.0"`
|
||||
Timeout time.Duration `yaml:"timeout" env:"OCM_OCM_INVITE_MANAGER_TIMEOUT" desc:"Timeout specifies a time limit for requests made to OCM endpoints." introductionVersion:"1.0.0"`
|
||||
Insecure bool `yaml:"insecure" env:"OCM_OCM_INVITE_MANAGER_INSECURE" desc:"Disable TLS certificate validation for the OCM connections. Do not set this in production environments." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMInviteManagerDrivers struct {
|
||||
JSON OCMInviteManagerJSONDriver `yaml:"json"`
|
||||
}
|
||||
|
||||
type OCMInviteManagerJSONDriver struct {
|
||||
File string `yaml:"file" env:"OCM_OCM_INVITE_MANAGER_JSON_FILE" desc:"Path to the JSON file where OCM invite data will be stored. This file is maintained by the instance and must not be changed manually. If not defined, the root directory derives from $OC_BASE_DATA_PATH/storage/ocm." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMProviderAuthorizerDrivers struct {
|
||||
JSON OCMProviderAuthorizerJSONDriver `yaml:"json"`
|
||||
}
|
||||
|
||||
type OCMProviderAuthorizerJSONDriver struct {
|
||||
Providers string `yaml:"providers" env:"OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE" desc:"Path to the JSON file where ocm invite data will be stored. Defaults to $OC_CONFIG_DIR/ocmproviders.json." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMCore struct {
|
||||
Driver string `yaml:"driver" env:"OCM_OCM_CORE_DRIVER" desc:"Driver to be used for the OCM core. Supported value is only 'json'." introductionVersion:"1.0.0"`
|
||||
Drivers OCMCoreDrivers `yaml:"drivers"`
|
||||
}
|
||||
type OCMStorageProvider struct {
|
||||
Insecure bool `yaml:"insecure" env:"OCM_OCM_STORAGE_PROVIDER_INSECURE" desc:"Disable TLS certificate validation for the OCM connections. Do not set this in production environments." introductionVersion:"1.0.0"`
|
||||
StorageRoot string `yaml:"storage_root" env:"OCM_OCM_STORAGE_PROVIDER_STORAGE_ROOT" desc:"Directory where the ocm storage provider persists its data like tus upload info files." introductionVersion:"1.0.0"`
|
||||
DataServerURL string `yaml:"data_server_url" env:"OCM_OCM_STORAGE_DATA_SERVER_URL" desc:"URL of the data server, needs to be reachable by the data gateway provided by the frontend service or the user if directly exposed." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMCoreDrivers struct {
|
||||
JSON OCMCoreJSONDriver `yaml:"json"`
|
||||
}
|
||||
|
||||
type OCMCoreJSONDriver struct {
|
||||
File string `yaml:"file" env:"OCM_OCM_CORE_JSON_FILE" desc:"Path to the JSON file where OCM share data will be stored. If not defined, the root directory derives from $OC_BASE_DATA_PATH/storage." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMShareProvider struct {
|
||||
Driver string `yaml:"driver" env:"OCM_OCM_SHARE_PROVIDER_DRIVER" desc:"Driver to be used for the OCM share provider. Supported value is only 'json'." introductionVersion:"1.0.0"`
|
||||
Drivers OCMShareProviderDrivers `yaml:"drivers"`
|
||||
Insecure bool `yaml:"insecure" env:"OCM_OCM_SHARE_PROVIDER_INSECURE" desc:"Disable TLS certificate validation for the OCM connections. Do not set this in production environments." introductionVersion:"1.0.0"`
|
||||
WebappTemplate string `yaml:"webapp_template" env:"OCM_WEBAPP_TEMPLATE" desc:"Template for the webapp url." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
type OCMShareProviderDrivers struct {
|
||||
JSON OCMShareProviderJSONDriver `yaml:"json"`
|
||||
}
|
||||
|
||||
type OCMShareProviderJSONDriver struct {
|
||||
File string `yaml:"file" env:"OCM_OCM_SHAREPROVIDER_JSON_FILE" desc:"Path to the JSON file where OCM share data will be stored. If not defined, the root directory derives from $OC_BASE_DATA_PATH/storage." introductionVersion:"1.0.0"`
|
||||
}
|
||||
|
||||
// Events combine the configuration options for the event bus.
|
||||
type Events struct {
|
||||
Endpoint string `yaml:"endpoint" env:"OC_EVENTS_ENDPOINT;OCM_EVENTS_ENDPOINT" desc:"The address of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture." introductionVersion:"1.0.0"`
|
||||
Cluster string `yaml:"cluster" env:"OC_EVENTS_CLUSTER;OCM_EVENTS_CLUSTER" desc:"The clusterID of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture. Mandatory when using NATS as event system." introductionVersion:"1.0.0"`
|
||||
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;OC_EVENTS_TLS_INSECURE;OCM_EVENTS_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"1.0.0"`
|
||||
TLSRootCACertificate string `yaml:"tls_root_ca_certificate" env:"OC_EVENTS_TLS_ROOT_CA_CERTIFICATE;OCM_EVENTS_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided OCM_EVENTS_TLS_INSECURE will be seen as false." introductionVersion:"1.0.0"`
|
||||
EnableTLS bool `yaml:"enable_tls" env:"OC_EVENTS_ENABLE_TLS;OCM_EVENTS_ENABLE_TLS" desc:"Enable TLS for the connection to the events broker. The events broker is the КуСфера service which receives and delivers events between the services." introductionVersion:"1.0.0"`
|
||||
AuthUsername string `yaml:"username" env:"OC_EVENTS_AUTH_USERNAME;OCM_EVENTS_AUTH_USERNAME" desc:"The username to authenticate with the events broker. The events broker is the КуСфера service which receives and delivers events between the services." introductionVersion:"1.0.0"`
|
||||
AuthPassword string `yaml:"password" env:"OC_EVENTS_AUTH_PASSWORD;OCM_EVENTS_AUTH_PASSWORD" desc:"The password to authenticate with the events broker. The events broker is the КуСфера service which receives and delivers events between the services." introductionVersion:"1.0.0"`
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
// Debug defines the available debug configuration.
|
||||
type Debug struct {
|
||||
Addr string `yaml:"addr" env:"OCM_DEBUG_ADDR" desc:"Bind address of the debug server, where metrics, health, config and debug endpoints will be exposed." introductionVersion:"1.0.0"`
|
||||
Token string `yaml:"token" env:"OCM_DEBUG_TOKEN" desc:"Token to secure the metrics endpoint." introductionVersion:"1.0.0"`
|
||||
Pprof bool `yaml:"pprof" env:"OCM_DEBUG_PPROF" desc:"Enables pprof, which can be used for profiling." introductionVersion:"1.0.0"`
|
||||
Zpages bool `yaml:"zpages" env:"OCM_DEBUG_ZPAGES" desc:"Enables zpages, which can be used for collecting and viewing in-memory traces." introductionVersion:"1.0.0"`
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package defaults
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/qsfera/server/pkg/config/defaults"
|
||||
"github.com/qsfera/server/pkg/shared"
|
||||
"github.com/qsfera/server/pkg/structs"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
)
|
||||
|
||||
// FullDefaultConfig returns the full default config
|
||||
func FullDefaultConfig() *config.Config {
|
||||
cfg := DefaultConfig()
|
||||
EnsureDefaults(cfg)
|
||||
Sanitize(cfg)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// DefaultConfig return the default configuration
|
||||
func DefaultConfig() *config.Config {
|
||||
return &config.Config{
|
||||
Debug: config.Debug{
|
||||
Addr: "127.0.0.1:9281",
|
||||
Token: "",
|
||||
Pprof: false,
|
||||
Zpages: false,
|
||||
},
|
||||
HTTP: config.HTTPConfig{
|
||||
Addr: "127.0.0.1:9280",
|
||||
Namespace: "qsfera.web",
|
||||
Protocol: "tcp",
|
||||
Prefix: "",
|
||||
CORS: config.CORS{
|
||||
AllowedOrigins: []string{"https://localhost:9200"},
|
||||
AllowedMethods: []string{
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"GET",
|
||||
"PUT",
|
||||
"POST",
|
||||
"DELETE",
|
||||
"MKCOL",
|
||||
"PROPFIND",
|
||||
"PROPPATCH",
|
||||
"MOVE",
|
||||
"COPY",
|
||||
"REPORT",
|
||||
"SEARCH",
|
||||
},
|
||||
AllowedHeaders: []string{
|
||||
"Origin",
|
||||
"Accept",
|
||||
"Content-Type",
|
||||
"Depth",
|
||||
"Authorization",
|
||||
"Ocs-Apirequest",
|
||||
"If-None-Match",
|
||||
"If-Match",
|
||||
"Destination",
|
||||
"Overwrite",
|
||||
"X-Request-Id",
|
||||
"X-Requested-With",
|
||||
"Tus-Resumable",
|
||||
"Tus-Checksum-Algorithm",
|
||||
"Upload-Concat",
|
||||
"Upload-Length",
|
||||
"Upload-Metadata",
|
||||
"Upload-Defer-Length",
|
||||
"Upload-Expires",
|
||||
"Upload-Checksum",
|
||||
"Upload-Offset",
|
||||
"X-HTTP-Method-Override",
|
||||
"Cache-Control",
|
||||
},
|
||||
AllowCredentials: false,
|
||||
},
|
||||
},
|
||||
GRPC: config.GRPCConfig{
|
||||
Addr: "127.0.0.1:9282",
|
||||
Namespace: "qsfera.api",
|
||||
},
|
||||
Reva: shared.DefaultRevaConfig(),
|
||||
Service: config.Service{
|
||||
Name: "ocm",
|
||||
},
|
||||
Events: config.Events{
|
||||
Endpoint: "127.0.0.1:9233",
|
||||
Cluster: "qsfera-cluster",
|
||||
},
|
||||
ScienceMesh: config.ScienceMesh{
|
||||
Prefix: "sciencemesh",
|
||||
InviteAcceptDialog: "/open-cloud-mesh/accept-invite",
|
||||
},
|
||||
OCMD: config.OCMD{
|
||||
Prefix: "ocm",
|
||||
},
|
||||
OCMInviteManager: config.OCMInviteManager{
|
||||
Driver: "json",
|
||||
Drivers: config.OCMInviteManagerDrivers{
|
||||
JSON: config.OCMInviteManagerJSONDriver{
|
||||
File: filepath.Join(defaults.BaseDataPath(), "storage", "ocm", "ocminvites.json"),
|
||||
},
|
||||
},
|
||||
TokenExpiration: 24 * time.Hour,
|
||||
Timeout: 30 * time.Second,
|
||||
Insecure: false,
|
||||
},
|
||||
OCMProviderAuthorizerDriver: "json",
|
||||
OCMProviderAuthorizerDrivers: config.OCMProviderAuthorizerDrivers{
|
||||
JSON: config.OCMProviderAuthorizerJSONDriver{
|
||||
Providers: filepath.Join(defaults.BaseConfigPath(), "ocmproviders.json"),
|
||||
},
|
||||
},
|
||||
OCMShareProvider: config.OCMShareProvider{
|
||||
Driver: "json",
|
||||
Drivers: config.OCMShareProviderDrivers{
|
||||
JSON: config.OCMShareProviderJSONDriver{
|
||||
File: filepath.Join(defaults.BaseDataPath(), "storage", "ocm", "ocmshares.json"),
|
||||
},
|
||||
},
|
||||
Insecure: false,
|
||||
},
|
||||
OCMCore: config.OCMCore{
|
||||
Driver: "json",
|
||||
Drivers: config.OCMCoreDrivers{
|
||||
JSON: config.OCMCoreJSONDriver{
|
||||
File: filepath.Join(defaults.BaseDataPath(), "storage", "ocm", "ocmshares.json"),
|
||||
},
|
||||
},
|
||||
},
|
||||
OCMStorageProvider: config.OCMStorageProvider{
|
||||
Insecure: false,
|
||||
StorageRoot: filepath.Join(defaults.BaseDataPath(), "storage", "ocm"),
|
||||
DataServerURL: "http://localhost:9280/data",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureDefaults ensures the config contains default values
|
||||
func EnsureDefaults(cfg *config.Config) {
|
||||
if cfg.LogLevel == "" {
|
||||
cfg.LogLevel = "error"
|
||||
}
|
||||
|
||||
if cfg.Reva == nil && cfg.Commons != nil {
|
||||
cfg.Reva = structs.CopyOrZeroValue(cfg.Commons.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.GRPCClientTLS == nil && cfg.Commons != nil {
|
||||
cfg.GRPCClientTLS = structs.CopyOrZeroValue(cfg.Commons.GRPCClientTLS)
|
||||
}
|
||||
|
||||
if cfg.GRPC.TLS == nil && cfg.Commons != nil {
|
||||
cfg.GRPC.TLS = structs.CopyOrZeroValue(cfg.Commons.GRPCServiceTLS)
|
||||
}
|
||||
|
||||
if (cfg.Commons != nil && cfg.Commons.QsferaURL != "") &&
|
||||
(cfg.HTTP.CORS.AllowedOrigins == nil ||
|
||||
len(cfg.HTTP.CORS.AllowedOrigins) == 1 &&
|
||||
cfg.HTTP.CORS.AllowedOrigins[0] == "https://localhost:9200") {
|
||||
cfg.HTTP.CORS.AllowedOrigins = []string{cfg.Commons.QsferaURL}
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize sanitizes the config
|
||||
func Sanitize(cfg *config.Config) {
|
||||
// nothing to sanitize here atm
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
occfg "github.com/qsfera/server/pkg/config"
|
||||
"github.com/qsfera/server/pkg/shared"
|
||||
"github.com/qsfera/server/pkg/structs"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config/defaults"
|
||||
|
||||
"github.com/qsfera/server/pkg/config/envdecode"
|
||||
)
|
||||
|
||||
// ParseConfig loads configuration from known paths.
|
||||
func ParseConfig(cfg *config.Config) error {
|
||||
err := occfg.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)
|
||||
}
|
||||
|
||||
// Validate validates the config
|
||||
func Validate(cfg *config.Config) error {
|
||||
if cfg.GRPCClientTLS == nil && cfg.Commons != nil {
|
||||
cfg.GRPCClientTLS = structs.CopyOrZeroValue(cfg.Commons.GRPCClientTLS)
|
||||
}
|
||||
|
||||
if cfg.ServiceAccount.ID == "" {
|
||||
return shared.MissingServiceAccountID(cfg.Service.Name)
|
||||
}
|
||||
if cfg.ServiceAccount.Secret == "" {
|
||||
return shared.MissingServiceAccountSecret(cfg.Service.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
// TokenManager is the config for using the reva token manager
|
||||
type TokenManager struct {
|
||||
JWTSecret string `yaml:"jwt_secret" env:"OC_JWT_SECRET;OCM_JWT_SECRET" desc:"The secret to mint and validate jwt tokens." introductionVersion:"1.0.0"`
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
// Service defines the available service configuration.
|
||||
type Service struct {
|
||||
Name string `yaml:"-"`
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package metrics
|
||||
|
||||
import "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
var (
|
||||
// Namespace defines the namespace for the defines metrics.
|
||||
Namespace = "qsfera"
|
||||
|
||||
// Subsystem defines the subsystem for the defines metrics.
|
||||
Subsystem = "ocm"
|
||||
)
|
||||
|
||||
// Metrics defines the available metrics of this service.
|
||||
type Metrics struct {
|
||||
BuildInfo *prometheus.GaugeVec
|
||||
}
|
||||
|
||||
// New initializes the available metrics.
|
||||
func New() *Metrics {
|
||||
m := &Metrics{
|
||||
BuildInfo: prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: Namespace,
|
||||
Subsystem: Subsystem,
|
||||
Name: "build_info",
|
||||
Help: "Build information",
|
||||
}, []string{"version"}),
|
||||
}
|
||||
|
||||
_ = prometheus.Register(
|
||||
m.BuildInfo,
|
||||
)
|
||||
|
||||
// TODO: implement metrics
|
||||
return m
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package revaconfig
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net/url"
|
||||
|
||||
"github.com/qsfera/server/pkg/log"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
)
|
||||
|
||||
// OCMConfigFromStruct will adapt a КуСфера config struct into a reva mapstructure to start a reva service.
|
||||
func OCMConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]any {
|
||||
|
||||
// Construct the ocm provider domain from the КуСфера URL
|
||||
providerDomain := ""
|
||||
u, err := url.Parse(cfg.Commons.QsferaURL)
|
||||
switch {
|
||||
case err != nil:
|
||||
logger.Error().Err(err).Msg("could not parse КуСфера URL")
|
||||
case u.Host == "КуСфера":
|
||||
logger.Error().Msg("КуСфера URL has no host")
|
||||
default:
|
||||
providerDomain = u.Host
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"shared": map[string]any{
|
||||
"jwt_secret": cfg.TokenManager.JWTSecret,
|
||||
"gatewaysvc": cfg.Reva.Address, // Todo or address?
|
||||
"grpc_client_options": cfg.Reva.GetGRPCClientConfig(),
|
||||
"multi_tenant_enabled": cfg.Commons.MultiTenantEnabled,
|
||||
},
|
||||
"http": map[string]any{
|
||||
"network": cfg.HTTP.Protocol,
|
||||
"address": cfg.HTTP.Addr,
|
||||
"middlewares": map[string]any{
|
||||
"cors": map[string]any{
|
||||
"allowed_origins": cfg.HTTP.CORS.AllowedOrigins,
|
||||
"allowed_methods": cfg.HTTP.CORS.AllowedMethods,
|
||||
"allowed_headers": cfg.HTTP.CORS.AllowedHeaders,
|
||||
"allow_credentials": cfg.HTTP.CORS.AllowCredentials,
|
||||
// currently unused
|
||||
//"options_passthrough": ,
|
||||
//"debug": ,
|
||||
//"max_age": ,
|
||||
//"priority": ,
|
||||
//"exposed_headers": ,
|
||||
},
|
||||
"auth": map[string]any{
|
||||
"credentials_by_user_agent": cfg.Middleware.Auth.CredentialsByUserAgent,
|
||||
},
|
||||
"prometheus": map[string]any{
|
||||
"namespace": "qsfera",
|
||||
"subsystem": "ocm",
|
||||
},
|
||||
"requestid": map[string]any{},
|
||||
},
|
||||
// TODO build services dynamically
|
||||
"services": map[string]any{
|
||||
"wellknown": map[string]any{
|
||||
"prefix": ".well-known",
|
||||
"ocmprovider": map[string]any{
|
||||
"ocm_prefix": cfg.OCMD.Prefix,
|
||||
"endpoint": cfg.Commons.QsferaURL,
|
||||
"provider": "КуСфера",
|
||||
"webdav_root": "/dav/ocm",
|
||||
"webapp_root": cfg.ScienceMesh.Prefix,
|
||||
"invite_accept_dialog": cfg.ScienceMesh.InviteAcceptDialog,
|
||||
"enable_webapp": false,
|
||||
"enable_datatx": false,
|
||||
},
|
||||
},
|
||||
"sciencemesh": map[string]any{
|
||||
"prefix": cfg.ScienceMesh.Prefix,
|
||||
"smtp_credentials": map[string]string{},
|
||||
"gatewaysvc": cfg.Reva.Address,
|
||||
"mesh_directory_url": cfg.ScienceMesh.MeshDirectoryURL,
|
||||
"directory_service_urls": cfg.ScienceMesh.DirectoryServiceURLs,
|
||||
"ocm_client_insecure": cfg.ScienceMesh.OCMClientInsecure,
|
||||
"provider_domain": providerDomain,
|
||||
"events": map[string]any{
|
||||
"natsaddress": cfg.Events.Endpoint,
|
||||
"natsclusterid": cfg.Events.Cluster,
|
||||
"tlsinsecure": cfg.Events.TLSInsecure,
|
||||
"tlsrootcacertificate": cfg.Events.TLSRootCACertificate,
|
||||
"authusername": cfg.Events.AuthUsername,
|
||||
"authpassword": cfg.Events.AuthPassword,
|
||||
},
|
||||
},
|
||||
"ocmd": map[string]any{
|
||||
"prefix": cfg.OCMD.Prefix,
|
||||
"gatewaysvc": cfg.Reva.Address,
|
||||
"expose_recipient_display_name": cfg.OCMD.ExposeRecipientDisplayName,
|
||||
},
|
||||
"dataprovider": map[string]any{
|
||||
"prefix": "data",
|
||||
"driver": "ocmreceived",
|
||||
"drivers": map[string]any{
|
||||
"ocmreceived": map[string]any{
|
||||
"insecure": cfg.OCMStorageProvider.Insecure,
|
||||
"storage_root": cfg.OCMStorageProvider.StorageRoot,
|
||||
"service_account_id": cfg.ServiceAccount.ID,
|
||||
"service_account_secret": cfg.ServiceAccount.Secret,
|
||||
},
|
||||
},
|
||||
"data_txs": map[string]any{
|
||||
"simple": map[string]any{
|
||||
"cache_store": "noop",
|
||||
"cache_database": "system",
|
||||
"cache_table": "stat",
|
||||
},
|
||||
"spaces": map[string]any{
|
||||
"cache_store": "noop",
|
||||
"cache_database": "system",
|
||||
"cache_table": "stat",
|
||||
},
|
||||
"tus": map[string]any{
|
||||
"cache_store": "noop",
|
||||
"cache_database": "system",
|
||||
"cache_table": "stat",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"grpc": map[string]any{
|
||||
"network": cfg.GRPC.Protocol,
|
||||
"address": cfg.GRPC.Addr,
|
||||
"tls_settings": map[string]any{
|
||||
"enabled": cfg.GRPC.TLS.Enabled,
|
||||
"certificate": cfg.GRPC.TLS.Cert,
|
||||
"key": cfg.GRPC.TLS.Key,
|
||||
},
|
||||
"services": map[string]any{
|
||||
"ocminvitemanager": map[string]any{
|
||||
"driver": cfg.OCMInviteManager.Driver,
|
||||
"drivers": map[string]any{
|
||||
"json": map[string]any{
|
||||
"file": cfg.OCMInviteManager.Drivers.JSON.File,
|
||||
},
|
||||
},
|
||||
"provider_domain": providerDomain,
|
||||
"token_expiration": cfg.OCMInviteManager.TokenExpiration.String(),
|
||||
"ocm_timeout": int(math.Round(cfg.OCMInviteManager.Timeout.Seconds())),
|
||||
"ocm_insecure": cfg.OCMInviteManager.Insecure,
|
||||
},
|
||||
"ocmproviderauthorizer": map[string]any{
|
||||
"driver": cfg.OCMProviderAuthorizerDriver,
|
||||
"drivers": map[string]any{
|
||||
"json": map[string]any{
|
||||
"providers": cfg.OCMProviderAuthorizerDrivers.JSON.Providers,
|
||||
},
|
||||
},
|
||||
},
|
||||
"ocmshareprovider": map[string]any{
|
||||
"driver": cfg.OCMShareProvider.Driver,
|
||||
"drivers": map[string]any{
|
||||
"json": map[string]any{
|
||||
"file": cfg.OCMShareProvider.Drivers.JSON.File,
|
||||
},
|
||||
},
|
||||
"gatewaysvc": cfg.Reva.Address,
|
||||
"provider_domain": providerDomain,
|
||||
"webdav_endpoint": cfg.Commons.QsferaURL,
|
||||
"webapp_template": cfg.OCMShareProvider.WebappTemplate,
|
||||
"client_insecure": cfg.OCMShareProvider.Insecure,
|
||||
},
|
||||
"ocmcore": map[string]any{
|
||||
"driver": cfg.OCMCore.Driver,
|
||||
"drivers": map[string]any{
|
||||
"json": map[string]any{
|
||||
"file": cfg.OCMCore.Drivers.JSON.File,
|
||||
},
|
||||
},
|
||||
},
|
||||
"storageprovider": map[string]any{
|
||||
"driver": "ocmreceived",
|
||||
"drivers": map[string]any{
|
||||
"ocmreceived": map[string]any{
|
||||
"insecure": cfg.OCMStorageProvider.Insecure,
|
||||
"storage_root": cfg.OCMStorageProvider.StorageRoot,
|
||||
},
|
||||
},
|
||||
"data_server_url": cfg.OCMStorageProvider.DataServerURL,
|
||||
},
|
||||
"authprovider": map[string]any{
|
||||
"auth_manager": "ocmshares",
|
||||
"auth_managers": map[string]any{
|
||||
"ocmshares": map[string]any{
|
||||
"gatewaysvc": cfg.Reva.Address,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/qsfera/server/pkg/log"
|
||||
"github.com/qsfera/server/services/ocm/pkg/config"
|
||||
)
|
||||
|
||||
// Option defines a single option function.
|
||||
type Option func(o *Options)
|
||||
|
||||
// Options defines the available options for this package.
|
||||
type Options struct {
|
||||
Logger log.Logger
|
||||
Context context.Context
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
// newOptions initializes the available default options.
|
||||
func newOptions(opts ...Option) Options {
|
||||
opt := Options{}
|
||||
|
||||
for _, o := range opts {
|
||||
o(&opt)
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// Logger provides a function to set the logger option.
|
||||
func Logger(val log.Logger) Option {
|
||||
return func(o *Options) {
|
||||
o.Logger = val
|
||||
}
|
||||
}
|
||||
|
||||
// Context provides a function to set the context option.
|
||||
func Context(val context.Context) Option {
|
||||
return func(o *Options) {
|
||||
o.Context = val
|
||||
}
|
||||
}
|
||||
|
||||
// Config provides a function to set the config option.
|
||||
func Config(val *config.Config) Option {
|
||||
return func(o *Options) {
|
||||
o.Config = val
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/qsfera/server/pkg/checks"
|
||||
"github.com/qsfera/server/pkg/handlers"
|
||||
"github.com/qsfera/server/pkg/service/debug"
|
||||
"github.com/qsfera/server/pkg/version"
|
||||
)
|
||||
|
||||
// Server initializes the debug service and server.
|
||||
func Server(opts ...Option) (*http.Server, error) {
|
||||
options := newOptions(opts...)
|
||||
|
||||
healthHandlerConfiguration := handlers.NewCheckHandlerConfiguration().
|
||||
WithLogger(options.Logger).
|
||||
WithCheck("web reachability", checks.NewHTTPCheck(options.Config.HTTP.Addr))
|
||||
|
||||
readyHandlerConfiguration := healthHandlerConfiguration.
|
||||
WithCheck("nats reachability", checks.NewNatsCheck(options.Config.Events.Endpoint)).
|
||||
WithCheck("grpc reachability", checks.NewGRPCCheck(options.Config.GRPC.Addr))
|
||||
|
||||
return debug.NewService(
|
||||
debug.Logger(options.Logger),
|
||||
debug.Name(options.Config.Service.Name),
|
||||
debug.Version(version.GetString()),
|
||||
debug.Address(options.Config.Debug.Addr),
|
||||
debug.Token(options.Config.Debug.Token),
|
||||
debug.Pprof(options.Config.Debug.Pprof),
|
||||
debug.Zpages(options.Config.Debug.Zpages),
|
||||
debug.Health(handlers.NewCheckHandler(healthHandlerConfiguration)),
|
||||
debug.Ready(handlers.NewCheckHandler(readyHandlerConfiguration)),
|
||||
//debug.CorsAllowedOrigins(options.Config.HTTP.CORS.AllowedOrigins),
|
||||
//debug.CorsAllowedMethods(options.Config.HTTP.CORS.AllowedMethods),
|
||||
//debug.CorsAllowedHeaders(options.Config.HTTP.CORS.AllowedHeaders),
|
||||
//debug.CorsAllowCredentials(options.Config.HTTP.CORS.AllowCredentials),
|
||||
), nil
|
||||
}
|
||||
Reference in New Issue
Block a user