mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-30 00:40:27 -06:00
@@ -61,6 +61,7 @@ config = {
|
||||
"services/auth-basic",
|
||||
"services/auth-bearer",
|
||||
"services/auth-machine",
|
||||
"services/auth-service",
|
||||
"services/eventhistory",
|
||||
"services/frontend",
|
||||
"services/gateway",
|
||||
|
||||
1
Makefile
1
Makefile
@@ -26,6 +26,7 @@ OCIS_MODULES = \
|
||||
services/auth-basic \
|
||||
services/auth-bearer \
|
||||
services/auth-machine \
|
||||
services/auth-service \
|
||||
services/eventhistory \
|
||||
services/frontend \
|
||||
services/gateway \
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
authbasic "github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
|
||||
authbearer "github.com/owncloud/ocis/v2/services/auth-bearer/pkg/config"
|
||||
authmachine "github.com/owncloud/ocis/v2/services/auth-machine/pkg/config"
|
||||
authservice "github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
eventhistory "github.com/owncloud/ocis/v2/services/eventhistory/pkg/config"
|
||||
frontend "github.com/owncloud/ocis/v2/services/frontend/pkg/config"
|
||||
gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/config"
|
||||
@@ -83,6 +84,7 @@ type Config struct {
|
||||
AuthBasic *authbasic.Config `yaml:"auth_basic"`
|
||||
AuthBearer *authbearer.Config `yaml:"auth_bearer"`
|
||||
AuthMachine *authmachine.Config `yaml:"auth_machine"`
|
||||
AuthService *authservice.Config `yaml:"auth_service"`
|
||||
EventHistory *eventhistory.Config `yaml:"eventhistory"`
|
||||
Frontend *frontend.Config `yaml:"frontend"`
|
||||
Gateway *gateway.Config `yaml:"gateway"`
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
authbasic "github.com/owncloud/ocis/v2/services/auth-basic/pkg/config/defaults"
|
||||
authbearer "github.com/owncloud/ocis/v2/services/auth-bearer/pkg/config/defaults"
|
||||
authmachine "github.com/owncloud/ocis/v2/services/auth-machine/pkg/config/defaults"
|
||||
authservice "github.com/owncloud/ocis/v2/services/auth-service/pkg/config/defaults"
|
||||
eventhistory "github.com/owncloud/ocis/v2/services/eventhistory/pkg/config/defaults"
|
||||
frontend "github.com/owncloud/ocis/v2/services/frontend/pkg/config/defaults"
|
||||
gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/config/defaults"
|
||||
@@ -55,6 +56,7 @@ func DefaultConfig() *Config {
|
||||
AuthBasic: authbasic.DefaultConfig(),
|
||||
AuthBearer: authbearer.DefaultConfig(),
|
||||
AuthMachine: authmachine.DefaultConfig(),
|
||||
AuthService: authservice.DefaultConfig(),
|
||||
EventHistory: eventhistory.DefaultConfig(),
|
||||
Frontend: frontend.DefaultConfig(),
|
||||
Gateway: gateway.DefaultConfig(),
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
authbasic "github.com/owncloud/ocis/v2/services/auth-basic/pkg/command"
|
||||
authbearer "github.com/owncloud/ocis/v2/services/auth-bearer/pkg/command"
|
||||
authmachine "github.com/owncloud/ocis/v2/services/auth-machine/pkg/command"
|
||||
authservice "github.com/owncloud/ocis/v2/services/auth-service/pkg/command"
|
||||
eventhistory "github.com/owncloud/ocis/v2/services/eventhistory/pkg/command"
|
||||
frontend "github.com/owncloud/ocis/v2/services/frontend/pkg/command"
|
||||
gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/command"
|
||||
@@ -83,6 +84,11 @@ var svccmds = []register.Command{
|
||||
cfg.AuthMachine.Commons = cfg.Commons
|
||||
})
|
||||
},
|
||||
func(cfg *config.Config) *cli.Command {
|
||||
return ServiceCommand(cfg, cfg.AuthService.Service.Name, authservice.GetCommands(cfg.AuthService), func(c *config.Config) {
|
||||
cfg.AuthService.Commons = cfg.Commons
|
||||
})
|
||||
},
|
||||
func(cfg *config.Config) *cli.Command {
|
||||
return ServiceCommand(cfg, cfg.EventHistory.Service.Name, eventhistory.GetCommands(cfg.EventHistory), func(c *config.Config) {
|
||||
cfg.EventHistory.Commons = cfg.Commons
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
audit "github.com/owncloud/ocis/v2/services/audit/pkg/command"
|
||||
authbasic "github.com/owncloud/ocis/v2/services/auth-basic/pkg/command"
|
||||
authmachine "github.com/owncloud/ocis/v2/services/auth-machine/pkg/command"
|
||||
authservice "github.com/owncloud/ocis/v2/services/auth-service/pkg/command"
|
||||
eventhistory "github.com/owncloud/ocis/v2/services/eventhistory/pkg/command"
|
||||
frontend "github.com/owncloud/ocis/v2/services/frontend/pkg/command"
|
||||
gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/command"
|
||||
@@ -135,6 +136,11 @@ func NewService(options ...Option) (*Service, error) {
|
||||
cfg.AuthMachine.Commons = cfg.Commons
|
||||
return authmachine.Execute(cfg.AuthMachine)
|
||||
})
|
||||
reg(opts.Config.AuthService.Service.Name, func(ctx context.Context, cfg *ociscfg.Config) error {
|
||||
cfg.AuthService.Context = ctx
|
||||
cfg.AuthService.Commons = cfg.Commons
|
||||
return authservice.Execute(cfg.AuthService)
|
||||
})
|
||||
reg(opts.Config.EventHistory.Service.Name, func(ctx context.Context, cfg *ociscfg.Config) error {
|
||||
cfg.EventHistory.Context = ctx
|
||||
cfg.EventHistory.Commons = cfg.Commons
|
||||
|
||||
@@ -6,6 +6,14 @@ The `auth-basic` service is responsible for validating authentication of incomin
|
||||
|
||||
To enable `auth-basic`, you first must set `PROXY_ENABLE_BASIC_AUTH` to `true`.
|
||||
|
||||
## The `auth` Service Family
|
||||
|
||||
ocis uses serveral authentication services for different use cases. All services that start with `auth-` are part of the authentication service family. Each member authenticates requests with different scopes. As of now, these services exist:
|
||||
- `auth-basic` handles basic authentication
|
||||
- `auth-bearer` handles oidc authentication
|
||||
- `auth-machine` handles interservice authentication when a user is impersonated
|
||||
- `auth-service` handles interservice authentication when using service accounts
|
||||
|
||||
## Auth Managers
|
||||
|
||||
Since the `auth-basic` service does not do any validation itself, it needs to be configured with an authentication manager. One can use the `AUTH_BASIC_AUTH_MANAGER` environment variable to configure this. Currently only one auth manager is supported: `"ldap"`
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
The oCIS Auth Bearer service communicates with the configured OpenID Connect identity provider to authenticate requests. OpenID Connect is the default authentication mechanism for all clients: web, desktop and mobile. Basic auth is only used for testing and has to be explicity enabled.
|
||||
|
||||
## Built in OpenID Connect identity provider
|
||||
## The `auth` Service Family
|
||||
|
||||
ocis uses serveral authentication services for different use cases. All services that start with `auth-` are part of the authentication service family. Each member authenticates requests with different scopes. As of now, these services exist:
|
||||
- `auth-basic` handles basic authentication
|
||||
- `auth-bearer` handles oidc authentication
|
||||
- `auth-machine` handles interservice authentication when a user is impersonated
|
||||
- `auth-service` handles interservice authentication when using service accounts
|
||||
|
||||
## Built in OpenID Connect Identity Provider
|
||||
|
||||
A default oCIS deployment will start a [built in OpenID Connect identity provider](https://github.com/owncloud/ocis/tree/master/services/idp) but can be configured to use an external one as well.
|
||||
|
||||
|
||||
17
services/auth-machine/README.md
Normal file
17
services/auth-machine/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Auth-Machine
|
||||
|
||||
The oCIS Auth Machine is used for interservice communication when using user impersonation.
|
||||
|
||||
ocis uses serveral authentication services for different use cases. All services that start with `auth-` are part of the authentication service family. Each member authenticates requests with different scopes. As of now, these services exist:
|
||||
- `auth-basic` handles basic authentication
|
||||
- `auth-bearer` handles oidc authentication
|
||||
- `auth-machine` handles interservice authentication when a user is impersonated
|
||||
- `auth-service` handles interservice authentication when using service accounts
|
||||
|
||||
## User Impersonation
|
||||
|
||||
When one ocis service is trying to talk to other ocis services, it needs to authenticate itself. To do so, it will impersonate a user using the `auth-machine` service. It will then act on behalf of this user. Any action will show up as action of this specific user, which gets visible when e.g. logged in the audit log.
|
||||
|
||||
## Deprecation
|
||||
|
||||
With the upcoming `auth-service` service, the `auth-machine` service will be used less frequently and is probably a candidate for deprecation.
|
||||
37
services/auth-service/Makefile
Normal file
37
services/auth-service/Makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
SHELL := bash
|
||||
NAME := auth-service
|
||||
|
||||
include ../../.make/recursion.mk
|
||||
|
||||
############ tooling ############
|
||||
ifneq (, $(shell command -v go 2> /dev/null)) # suppress `command not found warnings` for non go targets in CI
|
||||
include ../../.bingo/Variables.mk
|
||||
endif
|
||||
|
||||
############ go tooling ############
|
||||
include ../../.make/go.mk
|
||||
|
||||
############ release ############
|
||||
include ../../.make/release.mk
|
||||
|
||||
############ docs generate ############
|
||||
include ../../.make/docs.mk
|
||||
|
||||
.PHONY: docs-generate
|
||||
docs-generate: config-docs-generate
|
||||
|
||||
############ generate ############
|
||||
include ../../.make/generate.mk
|
||||
|
||||
.PHONY: ci-go-generate
|
||||
ci-go-generate: # CI runs ci-node-generate automatically before this target
|
||||
|
||||
.PHONY: ci-node-generate
|
||||
ci-node-generate:
|
||||
|
||||
############ licenses ############
|
||||
.PHONY: ci-node-check-licenses
|
||||
ci-node-check-licenses:
|
||||
|
||||
.PHONY: ci-node-save-licenses
|
||||
ci-node-save-licenses:
|
||||
19
services/auth-service/README.md
Normal file
19
services/auth-service/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Auth-Service
|
||||
|
||||
The ocis Auth Service is used to authenticate service accounts. Compared to normal accounts, service accounts are ocis internal only and not available as ordinary users like via LDAP.
|
||||
|
||||
## The `auth` Service Family
|
||||
|
||||
ocis uses serveral authentication services for different use cases. All services that start with `auth-` are part of the authentication service family. Each member authenticates requests with different scopes. As of now, these services exist:
|
||||
- `auth-basic` handles basic authentication
|
||||
- `auth-bearer` handles oidc authentication
|
||||
- `auth-machine` handles interservice authentication when a user is impersonated
|
||||
- `auth-service` handles interservice authentication when using service accounts
|
||||
|
||||
## Service Accounts
|
||||
|
||||
Service accounts are user accounts that are only used for inter service communication. The users have no personal space, do not show up in user lists and cannot login via the UI. Service accounts can be configured in the settings service. Only the `admin` service user is available for now. Additionally to the actions it can do via its role, all service users can stat all files on all spaces.
|
||||
|
||||
## Configuring Service Accounts
|
||||
|
||||
By using the envvars `OCIS_SERVICE_ACCOUNT_ID` and `OCIS_SERVICE_ACCOUNT_SECRET`, one can configure the ID and the secret of the service user. The secret can be rotated regulary to increase security. For activating a new secret, all services where the envvars are used need to be restarted. The secret is always and only stored in memory and never written into any persistant store. Though you can use any string for the service account, it is recommmended to use a UUIDv4 string.
|
||||
14
services/auth-service/cmd/auth-service/main.go
Normal file
14
services/auth-service/cmd/auth-service/main.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/command"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config/defaults"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := command.Execute(defaults.DefaultConfig()); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
54
services/auth-service/pkg/command/health.go
Normal file
54
services/auth-service/pkg/command/health.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config/parser"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/logging"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Health is the entrypoint for the health command.
|
||||
func Health(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "health",
|
||||
Usage: "check health status",
|
||||
Category: "info",
|
||||
Before: func(c *cli.Context) error {
|
||||
return configlog.ReturnError(parser.ParseConfig(cfg))
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
logger := logging.Configure(cfg.Service.Name, cfg.Log)
|
||||
|
||||
resp, err := http.Get(
|
||||
fmt.Sprintf(
|
||||
"http://%s/healthz",
|
||||
cfg.Debug.Addr,
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logger.Fatal().
|
||||
Err(err).
|
||||
Msg("Failed to request health check")
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
logger.Fatal().
|
||||
Int("code", resp.StatusCode).
|
||||
Msg("Health seems to be in bad state")
|
||||
}
|
||||
|
||||
logger.Debug().
|
||||
Int("code", resp.StatusCode).
|
||||
Msg("Health got a good state")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
34
services/auth-service/pkg/command/root.go
Normal file
34
services/auth-service/pkg/command/root.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/clihelper"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// GetCommands provides all commands for this service
|
||||
func GetCommands(cfg *config.Config) cli.Commands {
|
||||
return []*cli.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 ocis-auth-service command.
|
||||
func Execute(cfg *config.Config) error {
|
||||
app := clihelper.DefaultApp(&cli.App{
|
||||
Name: "auth-service",
|
||||
Usage: "Provide service authentication for oCIS",
|
||||
Commands: GetCommands(cfg),
|
||||
})
|
||||
|
||||
return app.Run(os.Args)
|
||||
}
|
||||
99
services/auth-service/pkg/command/server.go
Normal file
99
services/auth-service/pkg/command/server.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/cs3org/reva/v2/cmd/revad/runtime"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/oklog/run"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/version"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config/parser"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/logging"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/revaconfig"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/server/debug"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/tracing"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Server is the entry point for the server command.
|
||||
func Server(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "server",
|
||||
Usage: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
|
||||
Category: "server",
|
||||
Before: func(c *cli.Context) error {
|
||||
return configlog.ReturnFatal(parser.ParseConfig(cfg))
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
logger := logging.Configure(cfg.Service.Name, cfg.Log)
|
||||
err := tracing.Configure(cfg, logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gr := run.Group{}
|
||||
ctx, cancel := defineContext(cfg)
|
||||
|
||||
defer cancel()
|
||||
|
||||
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
|
||||
|
||||
rcfg := revaconfig.AuthMachineConfigFromStruct(cfg)
|
||||
|
||||
gr.Add(func() error {
|
||||
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
|
||||
return nil
|
||||
}, func(err error) {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
Str("server", cfg.Service.Name).
|
||||
Msg("Shutting down server")
|
||||
|
||||
cancel()
|
||||
})
|
||||
|
||||
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(debugServer.ListenAndServe, func(_ error) {
|
||||
cancel()
|
||||
})
|
||||
|
||||
if !cfg.Supervised {
|
||||
sync.Trap(&gr, cancel)
|
||||
}
|
||||
|
||||
grpcSvc := registry.BuildGRPCService(cfg.GRPC.Namespace+"."+cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, version.GetString())
|
||||
if err := registry.RegisterService(ctx, grpcSvc, logger); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to register the grpc service")
|
||||
}
|
||||
|
||||
return gr.Run()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// defineContext sets the context for the service. If there is a context configured it will create a new child from it,
|
||||
// if not, it will create a root context that can be cancelled.
|
||||
func defineContext(cfg *config.Config) (context.Context, context.CancelFunc) {
|
||||
return func() (context.Context, context.CancelFunc) {
|
||||
if cfg.Context == nil {
|
||||
return context.WithCancel(context.Background())
|
||||
}
|
||||
return context.WithCancel(cfg.Context)
|
||||
}()
|
||||
}
|
||||
50
services/auth-service/pkg/command/version.go
Normal file
50
services/auth-service/pkg/command/version.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/version"
|
||||
|
||||
tw "github.com/olekukonko/tablewriter"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Version prints the service versions of all running instances.
|
||||
func Version(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "version",
|
||||
Usage: "print the version of this binary and the running service instances",
|
||||
Category: "info",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Version: " + version.GetString())
|
||||
fmt.Printf("Compiled: %s\n", version.Compiled())
|
||||
fmt.Println("")
|
||||
|
||||
reg := registry.GetRegistry()
|
||||
services, err := reg.GetService(cfg.GRPC.Namespace + "." + cfg.Service.Name)
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Errorf("could not get %s services from the registry: %v", cfg.Service.Name, err))
|
||||
return err
|
||||
}
|
||||
|
||||
if len(services) == 0 {
|
||||
fmt.Println("No running " + cfg.Service.Name + " service found.")
|
||||
return nil
|
||||
}
|
||||
|
||||
table := tw.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Version", "Address", "Id"})
|
||||
table.SetAutoFormatHeaders(false)
|
||||
for _, s := range services {
|
||||
for _, n := range s.Nodes {
|
||||
table.Append([]string{s.Version, n.Address, n.Id})
|
||||
}
|
||||
}
|
||||
table.Render()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
63
services/auth-service/pkg/config/config.go
Normal file
63
services/auth-service/pkg/config/config.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Commons *shared.Commons `yaml:"-"` // don't use this directly as configuration for a service
|
||||
Service Service `yaml:"-"`
|
||||
Tracing *Tracing `yaml:"tracing"`
|
||||
Log *Log `yaml:"log"`
|
||||
Debug Debug `yaml:"debug"`
|
||||
|
||||
GRPC GRPCConfig `yaml:"grpc"`
|
||||
|
||||
TokenManager *TokenManager `yaml:"token_manager"`
|
||||
Reva *shared.Reva `yaml:"reva"`
|
||||
|
||||
// TODO: when using multiple service accounts we need to find a way to configure them
|
||||
ServiceAccount ServiceAccount `yaml:"service_account"`
|
||||
|
||||
Supervised bool `yaml:"-"`
|
||||
Context context.Context `yaml:"-"`
|
||||
}
|
||||
type Tracing struct {
|
||||
Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;AUTH_SERVICE_TRACING_ENABLED" desc:"Activates tracing."`
|
||||
Type string `yaml:"type" env:"OCIS_TRACING_TYPE;AUTH_SERVICE_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now."`
|
||||
Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;AUTH_SERVICE_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent."`
|
||||
Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;AUTH_SERVICE_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset."`
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
Level string `yaml:"level" env:"OCIS_LOG_LEVEL;AUTH_SERVICE_LOG_LEVEL" desc:"The log level. Valid values are: 'panic', 'fatal', 'error', 'warn', 'info', 'debug', 'trace'."`
|
||||
Pretty bool `yaml:"pretty" env:"OCIS_LOG_PRETTY;AUTH_SERVICE_LOG_PRETTY" desc:"Activates pretty log output."`
|
||||
Color bool `yaml:"color" env:"OCIS_LOG_COLOR;AUTH_SERVICE_LOG_COLOR" desc:"Activates colorized log output."`
|
||||
File string `yaml:"file" env:"OCIS_LOG_FILE;AUTH_SERVICE_LOG_FILE" desc:"The path to the log file. Activates logging to this file if set."`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
Name string `yaml:"-"`
|
||||
}
|
||||
|
||||
type Debug struct {
|
||||
Addr string `yaml:"addr" env:"AUTH_SERVICE_DEBUG_ADDR" desc:"Bind address of the debug server, where metrics, health, config and debug endpoints will be exposed."`
|
||||
Token string `yaml:"token" env:"AUTH_SERVICE_DEBUG_TOKEN" desc:"Token to secure the metrics endpoint."`
|
||||
Pprof bool `yaml:"pprof" env:"AUTH_SERVICE_DEBUG_PPROF" desc:"Enables pprof, which can be used for profiling."`
|
||||
Zpages bool `yaml:"zpages" env:"AUTH_SERVICE_DEBUG_ZPAGES" desc:"Enables zpages, which can be used for collecting and viewing in-memory traces."`
|
||||
}
|
||||
|
||||
type GRPCConfig struct {
|
||||
Addr string `yaml:"addr" env:"AUTH_SERVICE_GRPC_ADDR" desc:"The bind address of the GRPC service."`
|
||||
TLS *shared.GRPCServiceTLS `yaml:"tls"`
|
||||
Namespace string `yaml:"-"`
|
||||
Protocol string `yaml:"protocol" env:"AUTH_SERVICE_GRPC_PROTOCOL" desc:"The transport protocol of the GRPC service."`
|
||||
}
|
||||
|
||||
// ServiceAccount is the configuration for the used service account
|
||||
type ServiceAccount struct {
|
||||
ServiceAccountID string `yaml:"service_account_id" env:"OCIS_SERVICE_ACCOUNT_ID;AUTH_SERVICE_SERVICE_ACCOUNT_ID" desc:"The ID of the service account the service should use. See the 'auth-service' service description for more details."`
|
||||
ServiceAccountSecret string `yaml:"service_account_secret" env:"OCIS_SERVICE_ACCOUNT_SECRET;AUTH_SERVICE_SERVICE_ACCOUNT_SECRET" desc:"The service account secret."`
|
||||
}
|
||||
87
services/auth-service/pkg/config/defaults/defaultconfig.go
Normal file
87
services/auth-service/pkg/config/defaults/defaultconfig.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package defaults
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/structs"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
)
|
||||
|
||||
// FullDefaultConfig returns a fully initialized default configuration
|
||||
func FullDefaultConfig() *config.Config {
|
||||
cfg := DefaultConfig()
|
||||
EnsureDefaults(cfg)
|
||||
Sanitize(cfg)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// DefaultConfig returns a basic default configuration
|
||||
func DefaultConfig() *config.Config {
|
||||
return &config.Config{
|
||||
Debug: config.Debug{
|
||||
Addr: "127.0.0.1:9169",
|
||||
Token: "",
|
||||
Pprof: false,
|
||||
Zpages: false,
|
||||
},
|
||||
GRPC: config.GRPCConfig{
|
||||
Addr: "127.0.0.1:9199",
|
||||
Namespace: "com.owncloud.api",
|
||||
Protocol: "tcp",
|
||||
},
|
||||
Service: config.Service{
|
||||
Name: "auth-service",
|
||||
},
|
||||
Reva: shared.DefaultRevaConfig(),
|
||||
ServiceAccount: config.ServiceAccount{
|
||||
ServiceAccountID: "service-user-id",
|
||||
ServiceAccountSecret: "secret-string",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureDefaults adds default values to the configuration if they are not set yet
|
||||
func EnsureDefaults(cfg *config.Config) {
|
||||
// provide with defaults for shared logging, since we need a valid destination address for "envdecode".
|
||||
if cfg.Log == nil && cfg.Commons != nil && cfg.Commons.Log != nil {
|
||||
cfg.Log = &config.Log{
|
||||
Level: cfg.Commons.Log.Level,
|
||||
Pretty: cfg.Commons.Log.Pretty,
|
||||
Color: cfg.Commons.Log.Color,
|
||||
File: cfg.Commons.Log.File,
|
||||
}
|
||||
} else if cfg.Log == nil {
|
||||
cfg.Log = &config.Log{}
|
||||
}
|
||||
// provide with defaults for shared tracing, since we need a valid destination address for "envdecode".
|
||||
if cfg.Tracing == nil && cfg.Commons != nil && cfg.Commons.Tracing != nil {
|
||||
cfg.Tracing = &config.Tracing{
|
||||
Enabled: cfg.Commons.Tracing.Enabled,
|
||||
Type: cfg.Commons.Tracing.Type,
|
||||
Endpoint: cfg.Commons.Tracing.Endpoint,
|
||||
Collector: cfg.Commons.Tracing.Collector,
|
||||
}
|
||||
} else if cfg.Tracing == nil {
|
||||
cfg.Tracing = &config.Tracing{}
|
||||
}
|
||||
|
||||
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.GRPC.TLS == nil && cfg.Commons != nil {
|
||||
cfg.GRPC.TLS = structs.CopyOrZeroValue(cfg.Commons.GRPCServiceTLS)
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize sanitized the configuration
|
||||
func Sanitize(cfg *config.Config) {
|
||||
// nothing to sanitize here atm
|
||||
}
|
||||
42
services/auth-service/pkg/config/parser/parse.go
Normal file
42
services/auth-service/pkg/config/parser/parse.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config/defaults"
|
||||
|
||||
"github.com/owncloud/ocis/v2/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)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
6
services/auth-service/pkg/config/reva.go
Normal file
6
services/auth-service/pkg/config/reva.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
// TokenManager is the config for using the reva token manager
|
||||
type TokenManager struct {
|
||||
JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;AUTH_MACHINE_JWT_SECRET" desc:"The secret to mint and validate jwt tokens."`
|
||||
}
|
||||
17
services/auth-service/pkg/logging/logging.go
Normal file
17
services/auth-service/pkg/logging/logging.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
)
|
||||
|
||||
// LoggerFromConfig initializes a service-specific logger instance.
|
||||
func Configure(name string, cfg *config.Log) log.Logger {
|
||||
return log.NewLogger(
|
||||
log.Name(name),
|
||||
log.Level(cfg.Level),
|
||||
log.Pretty(cfg.Pretty),
|
||||
log.Color(cfg.Color),
|
||||
log.File(cfg.File),
|
||||
)
|
||||
}
|
||||
53
services/auth-service/pkg/revaconfig/config.go
Normal file
53
services/auth-service/pkg/revaconfig/config.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package revaconfig
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
)
|
||||
|
||||
// AuthMachineConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service.
|
||||
func AuthMachineConfigFromStruct(cfg *config.Config) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"core": map[string]interface{}{
|
||||
"tracing_enabled": cfg.Tracing.Enabled,
|
||||
"tracing_exporter": cfg.Tracing.Type,
|
||||
"tracing_endpoint": cfg.Tracing.Endpoint,
|
||||
"tracing_collector": cfg.Tracing.Collector,
|
||||
"tracing_service_name": cfg.Service.Name,
|
||||
},
|
||||
"shared": map[string]interface{}{
|
||||
"jwt_secret": cfg.TokenManager.JWTSecret,
|
||||
"gatewaysvc": cfg.Reva.Address,
|
||||
"grpc_client_options": cfg.Reva.GetGRPCClientConfig(),
|
||||
},
|
||||
"grpc": map[string]interface{}{
|
||||
"network": cfg.GRPC.Protocol,
|
||||
"address": cfg.GRPC.Addr,
|
||||
"tls_settings": map[string]interface{}{
|
||||
"enabled": cfg.GRPC.TLS.Enabled,
|
||||
"certificate": cfg.GRPC.TLS.Cert,
|
||||
"key": cfg.GRPC.TLS.Key,
|
||||
},
|
||||
"services": map[string]interface{}{
|
||||
"authprovider": map[string]interface{}{
|
||||
"auth_manager": "serviceaccounts",
|
||||
"auth_managers": map[string]interface{}{
|
||||
"serviceaccounts": map[string]interface{}{
|
||||
"service_accounts": []map[string]interface{}{
|
||||
{
|
||||
"id": cfg.ServiceAccount.ServiceAccountID,
|
||||
"secret": cfg.ServiceAccount.ServiceAccountSecret,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"interceptors": map[string]interface{}{
|
||||
"prometheus": map[string]interface{}{
|
||||
"namespace": "ocis",
|
||||
"subsystem": "auth_service",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
50
services/auth-service/pkg/server/debug/option.go
Normal file
50
services/auth-service/pkg/server/debug/option.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/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
|
||||
}
|
||||
}
|
||||
63
services/auth-service/pkg/server/debug/server.go
Normal file
63
services/auth-service/pkg/server/debug/server.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/service/debug"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/version"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
)
|
||||
|
||||
// Server initializes the debug service and server.
|
||||
func Server(opts ...Option) (*http.Server, error) {
|
||||
options := newOptions(opts...)
|
||||
|
||||
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(health(options.Config)),
|
||||
debug.Ready(ready(options.Config)),
|
||||
//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
|
||||
}
|
||||
|
||||
// health implements the health check.
|
||||
func health(cfg *config.Config) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
// TODO: check if services are up and running
|
||||
|
||||
_, err := io.WriteString(w, http.StatusText(http.StatusOK))
|
||||
// io.WriteString should not fail but if it does we want to know.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ready implements the ready check.
|
||||
func ready(cfg *config.Config) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
// TODO: check if services are up and running
|
||||
|
||||
_, err := io.WriteString(w, http.StatusText(http.StatusOK))
|
||||
// io.WriteString should not fail but if it does we want to know.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
25
services/auth-service/pkg/tracing/tracing.go
Normal file
25
services/auth-service/pkg/tracing/tracing.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/auth-service/pkg/config"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
pkgtrace "github.com/owncloud/ocis/v2/ocis-pkg/tracing"
|
||||
)
|
||||
|
||||
var (
|
||||
// TraceProvider is the global trace provider for the service.
|
||||
TraceProvider = trace.NewNoopTracerProvider()
|
||||
)
|
||||
|
||||
func Configure(cfg *config.Config, logger log.Logger) error {
|
||||
var err error
|
||||
if cfg.Tracing.Enabled {
|
||||
if TraceProvider, err = pkgtrace.GetTraceProvider(cfg.Tracing.Endpoint, cfg.Tracing.Collector, cfg.Service.Name, cfg.Tracing.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -38,6 +38,7 @@ type Config struct {
|
||||
AuthBasicEndpoint string `yaml:"-"`
|
||||
AuthBearerEndpoint string `yaml:"-"`
|
||||
AuthMachineEndpoint string `yaml:"-"`
|
||||
AuthServiceEndpoint string `yaml:"-"`
|
||||
StoragePublicLinkEndpoint string `yaml:"-"`
|
||||
StorageUsersEndpoint string `yaml:"-"`
|
||||
StorageSharesEndpoint string `yaml:"-"`
|
||||
|
||||
@@ -55,6 +55,7 @@ func DefaultConfig() *config.Config {
|
||||
AppRegistryEndpoint: "com.owncloud.api.app-registry",
|
||||
AuthBasicEndpoint: "com.owncloud.api.auth-basic",
|
||||
AuthMachineEndpoint: "com.owncloud.api.auth-machine",
|
||||
AuthServiceEndpoint: "com.owncloud.api.auth-service",
|
||||
GroupsEndpoint: "com.owncloud.api.groups",
|
||||
PermissionsEndpoint: "com.owncloud.api.settings",
|
||||
SharingEndpoint: "com.owncloud.api.sharing",
|
||||
|
||||
@@ -80,9 +80,10 @@ func GatewayConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]i
|
||||
"drivers": map[string]interface{}{
|
||||
"static": map[string]interface{}{
|
||||
"rules": map[string]interface{}{
|
||||
"basic": cfg.AuthBasicEndpoint,
|
||||
"machine": cfg.AuthMachineEndpoint,
|
||||
"publicshares": cfg.StoragePublicLinkEndpoint,
|
||||
"basic": cfg.AuthBasicEndpoint,
|
||||
"machine": cfg.AuthMachineEndpoint,
|
||||
"publicshares": cfg.StoragePublicLinkEndpoint,
|
||||
"serviceaccounts": cfg.AuthServiceEndpoint,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user