Merge branch 'master' into config-doc-descriptions

This commit is contained in:
Willy Kloucek
2022-06-28 13:03:19 +02:00
1251 changed files with 4036 additions and 3957 deletions

View File

@@ -0,0 +1,37 @@
SHELL := bash
NAME := auth-basic
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:

View File

@@ -0,0 +1,14 @@
package main
import (
"os"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/command"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config/defaults"
)
func main() {
if err := command.Execute(defaults.DefaultConfig()); err != nil {
os.Exit(1)
}
}

View File

@@ -0,0 +1,57 @@
package command
import (
"fmt"
"net/http"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config/parser"
"github.com/owncloud/ocis/v2/services/auth-basic/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 {
err := parser.ParseConfig(cfg)
if err != nil {
fmt.Printf("%v", err)
}
return err
},
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
},
}
}

View File

@@ -0,0 +1,64 @@
package command
import (
"context"
"os"
"github.com/owncloud/ocis/v2/ocis-pkg/clihelper"
ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
"github.com/thejerf/suture/v4"
"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-basic command.
func Execute(cfg *config.Config) error {
app := clihelper.DefaultApp(&cli.App{
Name: "auth-basic",
Usage: "Provide basic authentication for oCIS",
Commands: GetCommands(cfg),
})
cli.HelpFlag = &cli.BoolFlag{
Name: "help,h",
Usage: "Show the help",
}
return app.Run(os.Args)
}
// SutureService allows for the auth-basic command to be embedded and supervised by a suture supervisor tree.
type SutureService struct {
cfg *config.Config
}
// NewSutureService creates a new auth-basic.SutureService
func NewSutureService(cfg *ociscfg.Config) suture.Service {
cfg.AuthBasic.Commons = cfg.Commons
return SutureService{
cfg: cfg.AuthBasic,
}
}
func (s SutureService) Serve(ctx context.Context) error {
s.cfg.Context = ctx
if err := Execute(s.cfg); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,121 @@
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/ldap"
"github.com/owncloud/ocis/v2/ocis-pkg/service/external"
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
"github.com/owncloud/ocis/v2/ocis-pkg/version"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config/parser"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/logging"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/revaconfig"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/server/debug"
"github.com/owncloud/ocis/v2/services/auth-basic/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 %s extension without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Before: func(c *cli.Context) error {
err := parser.ParseConfig(cfg)
if err != nil {
fmt.Printf("%v", err)
os.Exit(1)
}
return err
},
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.AuthBasicConfigFromStruct(cfg)
// the reva runtime calls os.Exit in the case of a failure and there is no way for the oCIS
// runtime to catch it and restart a reva service. Therefore we need to ensure the service has
// everything it needs, before starting the service.
// In this case: CA certificates
if cfg.AuthProvider == "ldap" {
ldapCfg := cfg.AuthProviders.LDAP
if err := ldap.WaitForCA(logger, ldapCfg.Insecure, ldapCfg.CACert); err != nil {
logger.Error().Err(err).Msg("The configured LDAP CA cert does not exist")
return err
}
}
gr.Add(func() error {
runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger))
return nil
}, func(_ error) {
logger.Info().
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)
}
if err := external.RegisterGRPCEndpoint(
ctx,
cfg.GRPC.Namespace+"."+cfg.Service.Name,
uuid.Must(uuid.NewV4()).String(),
cfg.GRPC.Addr,
version.GetString(),
logger,
); err != nil {
logger.Fatal().Err(err).Msg("failed to register the grpc endpoint")
}
return gr.Run()
},
}
}
// defineContext sets the context for the extension. 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)
}()
}

View 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-basic/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 extension 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
},
}
}

View File

@@ -0,0 +1,116 @@
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 *Reva `yaml:"reva"`
SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token" env:"AUTH_BASIC_SKIP_USER_GROUPS_IN_TOKEN" desc:"Disables the encoding of the user's group memberships in the reva access token. This reduces the token size, especially when users are members of a large number of groups."`
AuthProvider string `yaml:"auth_provider" env:"AUTH_BASIC_AUTH_PROVIDER" desc:"The auth provider which should be used by the service (e.g. 'ldap')."`
AuthProviders AuthProviders `yaml:"auth_providers"`
Supervised bool `yaml:"-"`
Context context.Context `yaml:"-"`
}
type Tracing struct {
Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;AUTH_BASIC_TRACING_ENABLED" desc:"Activates tracing."`
Type string `yaml:"type" env:"OCIS_TRACING_TYPE;AUTH_BASIC_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_BASIC_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent."`
Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;AUTH_BASIC_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_BASIC_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_BASIC_LOG_PRETTY" desc:"Activates pretty log output."`
Color bool `yaml:"color" env:"OCIS_LOG_COLOR;AUTH_BASIC_LOG_COLOR" desc:"Activates colorized log output."`
File string `yaml:"file" env:"OCIS_LOG_FILE;AUTH_BASIC_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_BASIC_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_BASIC_DEBUG_TOKEN" desc:"Token to secure the metrics endpoint"`
Pprof bool `yaml:"pprof" env:"AUTH_BASIC_DEBUG_PPROF" desc:"Enables pprof, which can be used for profiling"`
Zpages bool `yaml:"zpages" env:"AUTH_BASIC_DEBUG_ZPAGES" desc:"Enables zpages, which can be used for collecting and viewing traces in-memory."`
}
type GRPCConfig struct {
Addr string `yaml:"addr" env:"AUTH_BASIC_GRPC_ADDR" desc:"The bind address of the GRPC service."`
Namespace string `yaml:"-"`
Protocol string `yaml:"protocol" env:"AUTH_BASIC_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."`
}
type AuthProviders struct {
LDAP LDAPProvider `yaml:"ldap"`
OwnCloudSQL OwnCloudSQLProvider `yaml:"owncloudsql"`
JSON JSONProvider `yaml:"json,omitempty"` // not supported by the oCIS product, therefore not part of docs
}
type JSONProvider struct {
File string `yaml:"file,omitempty"`
}
type LDAPProvider struct {
URI string `yaml:"uri" env:"LDAP_URI;AUTH_BASIC_LDAP_URI" desc:"URI of the LDAP Server to connect to. Supported URI schemes are 'ldaps://' and 'ldap://'"`
CACert string `yaml:"ca_cert" env:"LDAP_CACERT;AUTH_BASIC_LDAP_CACERT" desc:"Path to a CA certificate file for validating the LDAP server's TLS certificate. If empty the system default CA bundle will be used."`
Insecure bool `yaml:"insecure" env:"LDAP_INSECURE;AUTH_BASIC_LDAP_INSECURE" desc:"Disable TLS certificate validation for the LDAP connections. Do not set this in production environments."`
BindDN string `yaml:"bind_dn" env:"LDAP_BIND_DN;AUTH_BASIC_LDAP_BIND_DN" desc:"LDAP DN to use for simple bind authentication with the target LDAP server."`
BindPassword string `yaml:"bind_password" env:"LDAP_BIND_PASSWORD;AUTH_BASIC_LDAP_BIND_PASSWORD" desc:"Password to use for authenticating the 'bind_dn'."`
UserBaseDN string `yaml:"user_base_dn" env:"LDAP_USER_BASE_DN;AUTH_BASIC_LDAP_USER_BASE_DN" desc:"Search base DN for looking up LDAP users."`
GroupBaseDN string `yaml:"group_base_dn" env:"LDAP_GROUP_BASE_DN;AUTH_BASIC_LDAP_GROUP_BASE_DN" desc:"Search base DN for looking up LDAP groups."`
UserScope string `yaml:"user_scope" env:"LDAP_USER_SCOPE;AUTH_BASIC_LDAP_USER_SCOPE" desc:"LDAP search scope to use when looking up users ('base', 'one', 'sub')."`
GroupScope string `yaml:"group_scope" env:"LDAP_GROUP_SCOPE;AUTH_BASIC_LDAP_GROUP_SCOPE" desc:"LDAP search scope to use when looking up gruops ('base', 'one', 'sub')."`
UserFilter string `yaml:"user_filter" env:"LDAP_USER_FILTER;AUTH_BASIC_LDAP_USER_FILTER" desc:"LDAP filter to add to the default filters for user search (e.g. '(objectclass=ownCloud)')."`
GroupFilter string `yaml:"group_filter" env:"LDAP_GROUP_FILTER;AUTH_BASIC_LDAP_GROUP_FILTER" desc:"LDAP filter to add to the default filters for group searches."`
UserObjectClass string `yaml:"user_object_class" env:"LDAP_USER_OBJECTCLASS;AUTH_BASIC_LDAP_USER_OBJECTCLASS" desc:"The object class to use for users in the default user search filter ('inetOrgPerson')."`
GroupObjectClass string `yaml:"group_object_class" env:"LDAP_GROUP_OBJECTCLASS;AUTH_BASIC_LDAP_GROUP_OBJECTCLASS" desc:"The object class to use for groups in the default group search filter ('groupOfNames'). "`
LoginAttributes []string `yaml:"login_attributes" env:"LDAP_LOGIN_ATTRIBUTES;AUTH_BASIC_LDAP_LOGIN_ATTRIBUTES" desc:"The user object attributes, that can be used for login."`
IDP string `yaml:"idp" env:"OCIS_URL;OCIS_OIDC_ISSUER;AUTH_BASIC_IDP_URL" desc:"The identity provider value to set in the userids of the CS3 user objects for users returned by this user provider."`
UserSchema LDAPUserSchema `yaml:"user_schema"`
GroupSchema LDAPGroupSchema `yaml:"group_schema"`
}
type LDAPUserSchema struct {
ID string `yaml:"id" env:"LDAP_USER_SCHEMA_ID;AUTH_BASIC_LDAP_USER_SCHEMA_ID" desc:"LDAP Attribute to use as the unique id for users. This should be a stable globally unique id (e.g. a UUID)."`
IDIsOctetString bool `yaml:"id_is_octet_string" env:"LDAP_USER_SCHEMA_ID_IS_OCTETSTRING;AUTH_BASIC_LDAP_USER_SCHEMA_ID_IS_OCTETSTRING" desc:"Set this to true if the defined 'id' attribute for users is of the 'OCTETSTRING' syntax. This is e.g. required when using the 'objectGUID' attribute of Active Directory for the user ids."`
Mail string `yaml:"mail" env:"LDAP_USER_SCHEMA_MAIL;AUTH_BASIC_LDAP_USER_SCHEMA_MAIL" desc:"LDAP Attribute to use for the email address of users."`
DisplayName string `yaml:"display_name" env:"LDAP_USER_SCHEMA_DISPLAYNAME;AUTH_BASIC_LDAP_USER_SCHEMA_DISPLAYNAME" desc:"LDAP Attribute to use for the displayname of users."`
Username string `yaml:"user_name" env:"LDAP_USER_SCHEMA_USERNAME;AUTH_BASIC_LDAP_USER_SCHEMA_USERNAME" desc:"LDAP Attribute to use for username of users."`
}
type LDAPGroupSchema struct {
ID string `yaml:"id" env:"LDAP_GROUP_SCHEMA_ID;AUTH_BASIC_LDAP_GROUP_SCHEMA_ID" desc:"LDAP Attribute to use as the unique id for groups. This should be a stable globally unique id (e.g. a UUID)."`
IDIsOctetString bool `yaml:"id_is_octet_string" env:"LDAP_GROUP_SCHEMA_ID_IS_OCTETSTRING;AUTH_BASIC_LDAP_GROUP_SCHEMA_ID_IS_OCTETSTRING" desc:"Set this to true if the defined 'id' attribute for groups is of the 'OCTETSTRING' syntax. This is e.g. required when using the 'objectGUID' attribute of Active Directory for the group ids."`
Mail string `yaml:"mail" env:"LDAP_GROUP_SCHEMA_MAIL;AUTH_BASIC_LDAP_GROUP_SCHEMA_MAIL" desc:"LDAP Attribute to use for the email address of groups (can be empty)."`
DisplayName string `yaml:"display_name" env:"LDAP_GROUP_SCHEMA_DISPLAYNAME;AUTH_BASIC_LDAP_GROUP_SCHEMA_DISPLAYNAME" desc:"LDAP Attribute to use for the displayname of groups (often the same as groupname attribute)"`
Groupname string `yaml:"group_name" env:"LDAP_GROUP_SCHEMA_GROUPNAME;AUTH_BASIC_LDAP_GROUP_SCHEMA_GROUPNAME" desc:"LDAP Attribute to use for the name of groups"`
Member string `yaml:"member" env:"LDAP_GROUP_SCHEMA_MEMBER;AUTH_BASIC_LDAP_GROUP_SCHEMA_MEMBER" desc:"LDAP Attribute that is used for group members."`
}
type OwnCloudSQLProvider struct {
DBUsername string `yaml:"db_username" env:"AUTH_BASIC_OWNCLOUDSQL_DB_USERNAME" desc:"Database user to use for authenticating with the owncloud database."`
DBPassword string `yaml:"db_password" env:"AUTH_BASIC_OWNCLOUDSQL_DB_PASSWORD" desc:"Password for the database user."`
DBHost string `yaml:"db_host" env:"AUTH_BASIC_OWNCLOUDSQL_DB_HOST" desc:"Hostname of the database server."`
DBPort int `yaml:"db_port" env:"AUTH_BASIC_OWNCLOUDSQL_DB_PORT" desc:"Network port to use for the database connection."`
DBName string `yaml:"db_name" env:"AUTH_BASIC_OWNCLOUDSQL_DB_NAME" desc:"Name of the owncloud database."`
IDP string `yaml:"idp" env:"AUTH_BASIC_OWNCLOUDSQL_IDP" desc:"The identity provider value to set in the userids of the CS3 user objects for users returned by this user provider."`
Nobody int64 `yaml:"nobody" env:"AUTH_BASIC_OWNCLOUDSQL_NOBODY" desc:"Fallback number if no numeric UID and GID properties are provided."`
JoinUsername bool `yaml:"join_username" env:"AUTH_BASIC_OWNCLOUDSQL_JOIN_USERNAME" desc:"Join the user properties table to read usernames"`
JoinOwnCloudUUID bool `yaml:"join_owncloud_uuid" env:"AUTH_BASIC_OWNCLOUDSQL_JOIN_OWNCLOUD_UUID" desc:"Join the user properties table to read user ids (boolean)."`
}

View File

@@ -0,0 +1,126 @@
package defaults
import (
"path/filepath"
"github.com/owncloud/ocis/v2/ocis-pkg/config/defaults"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
)
func FullDefaultConfig() *config.Config {
cfg := DefaultConfig()
EnsureDefaults(cfg)
Sanitize(cfg)
return cfg
}
func DefaultConfig() *config.Config {
return &config.Config{
Debug: config.Debug{
Addr: "127.0.0.1:9147",
Token: "",
Pprof: false,
Zpages: false,
},
GRPC: config.GRPCConfig{
Addr: "127.0.0.1:9146",
Namespace: "com.owncloud.api",
Protocol: "tcp",
},
Service: config.Service{
Name: "auth-basic",
},
Reva: &config.Reva{
Address: "127.0.0.1:9142",
},
AuthProvider: "ldap",
AuthProviders: config.AuthProviders{
LDAP: config.LDAPProvider{
URI: "ldaps://localhost:9235",
CACert: filepath.Join(defaults.BaseDataPath(), "idm", "ldap.crt"),
Insecure: false,
UserBaseDN: "ou=users,o=libregraph-idm",
GroupBaseDN: "ou=groups,o=libregraph-idm",
UserScope: "sub",
GroupScope: "sub",
LoginAttributes: []string{"uid", "mail"},
UserFilter: "",
GroupFilter: "",
UserObjectClass: "inetOrgPerson",
GroupObjectClass: "groupOfNames",
BindDN: "uid=reva,ou=sysusers,o=libregraph-idm",
IDP: "https://localhost:9200",
UserSchema: config.LDAPUserSchema{
ID: "ownclouduuid",
Mail: "mail",
DisplayName: "displayname",
Username: "uid",
},
GroupSchema: config.LDAPGroupSchema{
ID: "ownclouduuid",
Mail: "mail",
DisplayName: "cn",
Groupname: "cn",
Member: "member",
},
},
JSON: config.JSONProvider{},
OwnCloudSQL: config.OwnCloudSQLProvider{
DBUsername: "owncloud",
DBHost: "mysql",
DBPort: 3306,
DBName: "owncloud",
IDP: "https://localhost:9200",
Nobody: 90,
JoinUsername: false,
JoinOwnCloudUUID: false,
},
},
}
}
func EnsureDefaults(cfg *config.Config) {
// provide with defaults for shared logging, since we need a valid destination address for BindEnv.
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 BindEnv.
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.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{}
}
}
func Sanitize(cfg *config.Config) {
// nothing to sanitize here atm
}

View File

@@ -0,0 +1,46 @@
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-basic/pkg/config"
"github.com/owncloud/ocis/v2/services/auth-basic/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)
}
if cfg.AuthProviders.LDAP.BindPassword == "" && cfg.AuthProvider == "ldap" {
return shared.MissingLDAPBindPassword(cfg.Service.Name)
}
return nil
}

View File

@@ -0,0 +1,11 @@
package config
// Reva defines all available REVA configuration.
type Reva struct {
Address string `yaml:"address" env:"REVA_GATEWAY" desc:"The CS3 gateway endpoint."`
}
// TokenManager is the config for using the reva token manager
type TokenManager struct {
JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;AUTH_BASIC_JWT_SECRET" desc:"The secret to mint and validate jwt tokens."`
}

View File

@@ -0,0 +1,17 @@
package logging
import (
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/auth-basic/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),
)
}

View File

@@ -0,0 +1,83 @@
package revaconfig
import "github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
// AuthBasicConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service.
func AuthBasicConfigFromStruct(cfg *config.Config) map[string]interface{} {
rcfg := map[string]interface{}{
"core": map[string]interface{}{
"tracing_enabled": cfg.Tracing.Enabled,
"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,
"skip_user_groups_in_token": cfg.SkipUserGroupsInToken,
},
"grpc": map[string]interface{}{
"network": cfg.GRPC.Protocol,
"address": cfg.GRPC.Addr,
// TODO build services dynamically
"services": map[string]interface{}{
"authprovider": map[string]interface{}{
"auth_manager": cfg.AuthProvider,
"auth_managers": map[string]interface{}{
"json": map[string]interface{}{
"users": cfg.AuthProviders.JSON.File,
},
"ldap": ldapConfigFromString(cfg.AuthProviders.LDAP),
"owncloudsql": map[string]interface{}{
"dbusername": cfg.AuthProviders.OwnCloudSQL.DBUsername,
"dbpassword": cfg.AuthProviders.OwnCloudSQL.DBPassword,
"dbhost": cfg.AuthProviders.OwnCloudSQL.DBHost,
"dbport": cfg.AuthProviders.OwnCloudSQL.DBPort,
"dbname": cfg.AuthProviders.OwnCloudSQL.DBName,
"idp": cfg.AuthProviders.OwnCloudSQL.IDP,
"nobody": cfg.AuthProviders.OwnCloudSQL.Nobody,
"join_username": cfg.AuthProviders.OwnCloudSQL.JoinUsername,
"join_ownclouduuid": cfg.AuthProviders.OwnCloudSQL.JoinOwnCloudUUID,
},
},
},
},
},
}
return rcfg
}
func ldapConfigFromString(cfg config.LDAPProvider) map[string]interface{} {
return map[string]interface{}{
"uri": cfg.URI,
"cacert": cfg.CACert,
"insecure": cfg.Insecure,
"bind_username": cfg.BindDN,
"bind_password": cfg.BindPassword,
"user_base_dn": cfg.UserBaseDN,
"group_base_dn": cfg.GroupBaseDN,
"user_filter": cfg.UserFilter,
"group_filter": cfg.GroupFilter,
"user_scope": cfg.UserScope,
"group_scope": cfg.GroupScope,
"user_objectclass": cfg.UserObjectClass,
"group_objectclass": cfg.GroupObjectClass,
"login_attributes": cfg.LoginAttributes,
"idp": cfg.IDP,
"user_schema": map[string]interface{}{
"id": cfg.UserSchema.ID,
"idIsOctetString": cfg.UserSchema.IDIsOctetString,
"mail": cfg.UserSchema.Mail,
"displayName": cfg.UserSchema.DisplayName,
"userName": cfg.UserSchema.Username,
},
"group_schema": map[string]interface{}{
"id": cfg.GroupSchema.ID,
"idIsOctetString": cfg.GroupSchema.IDIsOctetString,
"mail": cfg.GroupSchema.Mail,
"displayName": cfg.GroupSchema.DisplayName,
"groupName": cfg.GroupSchema.Groupname,
"member": cfg.GroupSchema.Member,
},
}
}

View File

@@ -0,0 +1,50 @@
package debug
import (
"context"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/auth-basic/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
}
}

View 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-basic/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)
}
}
}

View File

@@ -0,0 +1,18 @@
package tracing
import (
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
"github.com/owncloud/ocis/v2/services/auth-basic/pkg/config"
"go.opentelemetry.io/otel/trace"
)
var (
// TraceProvider is the global trace provider for the service.
TraceProvider = trace.NewNoopTracerProvider()
)
func Configure(cfg *config.Config, logger log.Logger) error {
tracing.Configure(cfg.Tracing.Enabled, cfg.Tracing.Type, logger)
return nil
}