Merge branch 'master' into StoreSettingsViaMetadata

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2022-03-14 13:34:27 +01:00
218 changed files with 5063 additions and 1690 deletions
+9 -3
View File
@@ -16,6 +16,7 @@ config = {
"modules": [
# if you add a module here please also add it to the root level Makefile
"accounts",
"audit",
"glauth",
"graph-explorer",
"graph",
@@ -956,11 +957,16 @@ def binaryReleases(ctx):
return pipelines
def binaryRelease(ctx, name):
# uploads binary to https://download.owncloud.com/ocis/ocis/testing/
target = "/ocis/%s/testing" % (ctx.repo.name.replace("ocis-", ""))
# uploads binary to https://download.owncloud.com/ocis/ocis/daily/
target = "/ocis/%s/daily" % (ctx.repo.name.replace("ocis-", ""))
if ctx.build.event == "tag":
# uploads binary to eg. https://download.owncloud.com/ocis/ocis/1.0.0-beta9/
target = "/ocis/%s/%s" % (ctx.repo.name.replace("ocis-", ""), ctx.build.ref.replace("refs/tags/v", ""))
folder = "stable"
buildref = ctx.build.ref.replace("refs/tags/v", "")
buildref = buildref.lower()
if buildref.find("-") != -1: # "x.x.x-alpha", "x.x.x-beta", "x.x.x-rc"
folder = "testing"
target = "/ocis/%s/%s/%s" % (ctx.repo.name.replace("ocis-", ""), folder, buildref)
settings = {
"endpoint": {
+2 -2
View File
@@ -10,7 +10,7 @@ repository:
private: false
has_issues: true
has_projects: false
has_wiki: true
has_wiki: false
has_downloads: false
default_branch: master
@@ -35,7 +35,7 @@ labels:
color: "#3F7A62"
- name: Storage:ownCloudSQL
color: "#3F7A62"
teams:
- name: ci
permission: admin
+43
View File
@@ -6,15 +6,58 @@ The following sections list the changes for unreleased.
## Summary
* Bugfix - Network configuration in individiual_services example: [#3238](https://github.com/owncloud/ocis/pull/3238)
* Bugfix - Improve gif thumbnails: [#3305](https://github.com/owncloud/ocis/pull/3305)
* Enhancement - Log sharing events in audit service: [#3301](https://github.com/owncloud/ocis/pull/3301)
* Enhancement - Include etags in drives listing: [#3267](https://github.com/owncloud/ocis/pull/3267)
* Enhancement - Improve thumbnails API: [#3272](https://github.com/owncloud/ocis/pull/3272)
* Enhancement - Update ownCloud Web to v5.3.0-rc.1: [#6561](https://github.com/owncloud/web/pull/6561)
## Details
* Bugfix - Network configuration in individiual_services example: [#3238](https://github.com/owncloud/ocis/pull/3238)
Tidy up the deployments/examples/ocis_individual_services example so that the
instructions work.
https://github.com/owncloud/ocis/pull/3238
* Bugfix - Improve gif thumbnails: [#3305](https://github.com/owncloud/ocis/pull/3305)
Improved the gif thumbnail generation for gifs with different disposal strategies.
https://github.com/owncloud/ocis/pull/3305
* Enhancement - Log sharing events in audit service: [#3301](https://github.com/owncloud/ocis/pull/3301)
Contains sharing related events. See full list in audit/pkg/types/events.go
https://github.com/owncloud/ocis/pull/3301
* Enhancement - Include etags in drives listing: [#3267](https://github.com/owncloud/ocis/pull/3267)
Added etags in the response of list drives.
https://github.com/owncloud/ocis/pull/3267
* Enhancement - Improve thumbnails API: [#3272](https://github.com/owncloud/ocis/pull/3272)
Changed the thumbnails API to no longer transfer images via GRPC. GRPC has a limited message
size and isn't very efficient with large binary data. The new API transports the images over
HTTP.
https://github.com/owncloud/ocis/pull/3272
* Enhancement - Update ownCloud Web to v5.3.0-rc.1: [#6561](https://github.com/owncloud/web/pull/6561)
Tags: web
We updated ownCloud Web to v5.3.0-rc.1. Please refer to the changelog (linked) for details on
the web release.
https://github.com/owncloud/web/pull/6561
https://github.com/owncloud/ocis/pull/3291
https://github.com/owncloud/web/releases/tag/v5.3.0-rc.1
# Changelog for [1.18.0] (2022-03-03)
The following sections list the changes for 1.18.0.
+1
View File
@@ -17,6 +17,7 @@ L10N_MODULES := $(shell find . -path '*.tx*' -name 'config' | sed 's|/[^/]*$$||'
# if you add a module here please also add it to the .drone.star file
OCIS_MODULES = \
accounts \
audit \
glauth \
graph \
graph-explorer \
+2 -2
View File
@@ -4,11 +4,11 @@ import (
"os"
"github.com/owncloud/ocis/accounts/pkg/command"
"github.com/owncloud/ocis/accounts/pkg/config"
"github.com/owncloud/ocis/accounts/pkg/config/defaults"
)
func main() {
if err := command.Execute(config.DefaultConfig()); err != nil {
if err := command.Execute(defaults.DefaultConfig()); err != nil {
os.Exit(1)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"fmt"
accountsdefaults "github.com/owncloud/ocis/accounts/pkg/config/defaults"
idpdefaults "github.com/owncloud/ocis/idp/pkg/config/defaults"
"gopkg.in/yaml.v2"
)
func main() {
fn1 := accountsdefaults.FullDefaultConfig
fn2 := idpdefaults.FullDefaultConfig
b, err := yaml.Marshal(fn1())
if err != nil {
return
}
fmt.Println(string(b))
b, err = yaml.Marshal(fn2())
if err != nil {
return
}
fmt.Println(string(b))
}
+3 -3
View File
@@ -8,9 +8,9 @@ import (
// Config combines all available configuration parts.
type Config struct {
*shared.Commons
*shared.Commons `ocisConfig:"-" yaml:"-"`
Service Service
Service Service `ocisConfig:"-" yaml:"-"`
Tracing *Tracing `ocisConfig:"tracing"`
Log *Log `ocisConfig:"log"`
@@ -28,7 +28,7 @@ type Config struct {
HashDifficulty int `ocisConfig:"hash_difficulty" env:"ACCOUNTS_HASH_DIFFICULTY" desc:"The hash difficulty makes sure that validating a password takes at least a certain amount of time."`
DemoUsersAndGroups bool `ocisConfig:"demo_users_and_groups" env:"ACCOUNTS_DEMO_USERS_AND_GROUPS" desc:"If this flag is set the service will setup the demo users and groups."`
Context context.Context
Context context.Context `ocisConfig:"-" yaml:"-"`
}
// Asset defines the available asset configuration.
-68
View File
@@ -1,68 +0,0 @@
package config
import (
"path"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)
func DefaultConfig() *Config {
return &Config{
Debug: Debug{
Addr: "127.0.0.1:9182",
Token: "",
Pprof: false,
Zpages: false,
},
HTTP: HTTP{
Addr: "127.0.0.1:9181",
Namespace: "com.owncloud.web",
Root: "/",
CacheTTL: 604800, // 7 days
CORS: CORS{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Authorization", "Origin", "Content-Type", "Accept", "X-Requested-With"},
AllowCredentials: true,
},
},
GRPC: GRPC{
Addr: "127.0.0.1:9180",
Namespace: "com.owncloud.api",
},
Service: Service{
Name: "accounts",
},
Asset: Asset{},
TokenManager: TokenManager{
JWTSecret: "Pive-Fumkiu4",
},
HashDifficulty: 11,
DemoUsersAndGroups: true,
Repo: Repo{
Backend: "CS3",
Disk: Disk{
Path: path.Join(defaults.BaseDataPath(), "accounts"),
},
CS3: CS3{
ProviderAddr: "localhost:9215",
},
},
Index: Index{
UID: UIDBound{
Lower: 0,
Upper: 1000,
},
GID: GIDBound{
Lower: 0,
Upper: 1000,
},
},
ServiceUser: ServiceUser{
UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad",
// Username: "service user",
UID: 0,
GID: 0,
},
}
}
@@ -0,0 +1,112 @@
package defaults
import (
"path"
"strings"
"github.com/owncloud/ocis/accounts/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)
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:9182",
Token: "",
Pprof: false,
Zpages: false,
},
HTTP: config.HTTP{
Addr: "127.0.0.1:9181",
Namespace: "com.owncloud.web",
Root: "/",
CacheTTL: 604800, // 7 days
CORS: config.CORS{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Authorization", "Origin", "Content-Type", "Accept", "X-Requested-With"},
AllowCredentials: true,
},
},
GRPC: config.GRPC{
Addr: "127.0.0.1:9180",
Namespace: "com.owncloud.api",
},
Service: config.Service{
Name: "accounts",
},
Asset: config.Asset{},
TokenManager: config.TokenManager{
JWTSecret: "Pive-Fumkiu4",
},
HashDifficulty: 11,
DemoUsersAndGroups: true,
Repo: config.Repo{
Backend: "CS3",
Disk: config.Disk{
Path: path.Join(defaults.BaseDataPath(), "accounts"),
},
CS3: config.CS3{
ProviderAddr: "localhost:9215",
},
},
Index: config.Index{
UID: config.UIDBound{
Lower: 0,
Upper: 1000,
},
GID: config.GIDBound{
Lower: 0,
Upper: 1000,
},
},
ServiceUser: config.ServiceUser{
UUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad",
Username: "",
UID: 0,
GID: 0,
},
}
}
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{}
}
}
func Sanitize(cfg *config.Config) {
// sanitize config
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/")
}
cfg.Repo.Backend = strings.ToLower(cfg.Repo.Backend)
}
+1 -1
View File
@@ -3,5 +3,5 @@ package config
// GRPC defines the available grpc configuration.
type GRPC struct {
Addr string `ocisConfig:"addr" env:"ACCOUNTS_GRPC_ADDR" desc:"The address of the grpc service."`
Namespace string
Namespace string `ocisConfig:"-" yaml:"-"`
}
+2 -2
View File
@@ -3,10 +3,10 @@ package config
// HTTP defines the available http configuration.
type HTTP struct {
Addr string `ocisConfig:"addr" env:"ACCOUNTS_HTTP_ADDR" desc:"The address of the http service."`
Namespace string
Namespace string `ocisConfig:"-" yaml:"-"`
Root string `ocisConfig:"root" env:"ACCOUNTS_HTTP_ROOT" desc:"The root path of the http service."`
CacheTTL int `ocisConfig:"cache_ttl" env:"ACCOUNTS_CACHE_TTL" desc:"The cache time for the static assets."`
CORS CORS
CORS CORS `ocisConfig:"cors"`
}
// CORS defines the available cors configuration.
+5 -30
View File
@@ -2,11 +2,11 @@ package parser
import (
"errors"
"strings"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/accounts/pkg/config"
defaults "github.com/owncloud/ocis/accounts/pkg/config/defaults"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
)
@@ -17,28 +17,7 @@ func ParseConfig(cfg *config.Config) error {
return err
}
// 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{}
}
defaults.EnsureDefaults(cfg)
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
@@ -48,11 +27,7 @@ func ParseConfig(cfg *config.Config) error {
}
}
// sanitize config
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/")
}
cfg.Repo.Backend = strings.ToLower(cfg.Repo.Backend)
defaults.Sanitize(cfg)
return nil
}
+1 -1
View File
@@ -2,5 +2,5 @@ package config
// Service defines the available service configuration.
type Service struct {
Name string
Name string `ocisConfig:"-" yaml:"-"`
}
@@ -13,7 +13,7 @@ import (
accountssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/accounts/v0"
"github.com/golang/protobuf/ptypes/empty"
"github.com/owncloud/ocis/accounts/pkg/config"
config "github.com/owncloud/ocis/accounts/pkg/config/defaults"
olog "github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/middleware"
"github.com/owncloud/ocis/ocis-pkg/roles"
+23
View File
@@ -253,6 +253,25 @@ func (s Service) createDefaultAccounts(withDemoAccounts bool) (err error) {
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"}, // users
},
},
{
Id: "534bb038-6f9d-4093-946f-133be61fa4e7",
PreferredName: "katherine",
OnPremisesSamAccountName: "katherine",
Mail: "katherine@example.org",
DisplayName: "Katherine Johnson",
UidNumber: 20005,
GidNumber: 30000,
PasswordProfile: &accountsmsg.PasswordProfile{
Password: "$2a$11$6SIBlZ.8BzjBsDTRrThUyuz6OvP.XLo7101oFiwHHB.jufKGS9.Ji",
},
AccountEnabled: true,
MemberOf: []*accountsmsg.Group{
{Id: "509a9dcd-bb37-4f4f-a01a-19dca27d9cfa"}, // users
{Id: "6040aa17-9c64-4fef-9bd0-77234d71bad0"}, // sailing-lovers
{Id: "a1726108-01f8-4c30-88df-2b1a9d1cba1a"}, // quantum-lovers
{Id: "262982c1-2362-4afa-bfdf-8cbfef64a06e"}, // physics-lovers
},
},
// technical users for kopano and reva
{
Id: "820ba2a1-3f54-4538-80a4-2d73007e30bf",
@@ -353,9 +372,11 @@ func (s Service) createDefaultGroups(withDemoGroups bool) (err error) {
{Id: "4c510ada-c86b-4815-8820-42cdf82c3d51"}, // einstein
{Id: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c"}, // marie
{Id: "932b4540-8d16-481e-8ef4-588e4b6b151c"}, // feynman
{Id: "534bb038-6f9d-4093-946f-133be61fa4e7"}, // katherine
}},
{Id: "6040aa17-9c64-4fef-9bd0-77234d71bad0", GidNumber: 30001, OnPremisesSamAccountName: "sailing-lovers", DisplayName: "Sailing lovers", Members: []*accountsmsg.Account{
{Id: "4c510ada-c86b-4815-8820-42cdf82c3d51"}, // einstein
{Id: "534bb038-6f9d-4093-946f-133be61fa4e7"}, // katherine
}},
{Id: "dd58e5ec-842e-498b-8800-61f2ec6f911f", GidNumber: 30002, OnPremisesSamAccountName: "violin-haters", DisplayName: "Violin haters", Members: []*accountsmsg.Account{
{Id: "4c510ada-c86b-4815-8820-42cdf82c3d51"}, // einstein
@@ -368,6 +389,7 @@ func (s Service) createDefaultGroups(withDemoGroups bool) (err error) {
}},
{Id: "a1726108-01f8-4c30-88df-2b1a9d1cba1a", GidNumber: 30005, OnPremisesSamAccountName: "quantum-lovers", DisplayName: "Quantum lovers", Members: []*accountsmsg.Account{
{Id: "932b4540-8d16-481e-8ef4-588e4b6b151c"}, // feynman
{Id: "534bb038-6f9d-4093-946f-133be61fa4e7"}, // katherine
}},
{Id: "167cbee2-0518-455a-bfb2-031fe0621e5d", GidNumber: 30006, OnPremisesSamAccountName: "philosophy-haters", DisplayName: "Philosophy haters", Members: []*accountsmsg.Account{
{Id: "932b4540-8d16-481e-8ef4-588e4b6b151c"}, // feynman
@@ -376,6 +398,7 @@ func (s Service) createDefaultGroups(withDemoGroups bool) (err error) {
{Id: "4c510ada-c86b-4815-8820-42cdf82c3d51"}, // einstein
{Id: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c"}, // marie
{Id: "932b4540-8d16-481e-8ef4-588e4b6b151c"}, // feynman
{Id: "534bb038-6f9d-4093-946f-133be61fa4e7"}, // katherine
}},
}
+55
View File
@@ -0,0 +1,55 @@
SHELL := bash
NAME := audit
include ../.make/recursion.mk
.PHONY: test-acceptance-webui
test-acceptance-webui:
./ui/tests/run-acceptance-test.sh $(FEATURE_PATH)
############ tooling ############
ifneq (, $(shell which 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
############ l10n ############
include ../.make/l10n.mk
.PHONY: docs-generate
docs-generate: config-docs-generate \
grpc-docs-generate
############ generate ############
include ../.make/generate.mk
.PHONY: ci-go-generate
ci-go-generate: protobuf # CI runs ci-node-generate automatically before this target
.PHONY: ci-node-generate
ci-node-generate: yarn-build
.PHONY: yarn-build
yarn-build: node_modules
yarn lint
yarn test
yarn build
.PHONY: node_modules
node_modules:
yarn install --immutable
############ protobuf ############
include ../.make/protobuf.mk
.PHONY: protobuf
protobuf: buf-generate
+14
View File
@@ -0,0 +1,14 @@
package main
import (
"os"
"github.com/owncloud/ocis/audit/pkg/command"
"github.com/owncloud/ocis/audit/pkg/config"
)
func main() {
if err := command.Execute(config.DefaultConfig()); err != nil {
os.Exit(1)
}
}
+18
View File
@@ -0,0 +1,18 @@
package command
import (
"github.com/owncloud/ocis/audit/pkg/config"
"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",
Action: func(c *cli.Context) error {
// Not implemented
return nil
},
}
}
+64
View File
@@ -0,0 +1,64 @@
package command
import (
"context"
"os"
"github.com/owncloud/ocis/audit/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/clihelper"
ociscfg "github.com/owncloud/ocis/ocis-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 audit command.
func Execute(cfg *config.Config) error {
app := clihelper.DefaultApp(&cli.App{
Name: "audit",
Usage: "starts audit service",
Commands: GetCommands(cfg),
})
cli.HelpFlag = &cli.BoolFlag{
Name: "help,h",
Usage: "Show the help",
}
return app.Run(os.Args)
}
// SutureService allows for the audit command to be embedded and supervised by a suture supervisor tree.
type SutureService struct {
cfg *config.Config
}
// NewSutureService creates a new audit.SutureService
func NewSutureService(cfg *ociscfg.Config) suture.Service {
cfg.Settings.Commons = cfg.Commons
return SutureService{
cfg: cfg.Audit,
}
}
func (s SutureService) Serve(ctx context.Context) error {
s.cfg.Context = ctx
if err := Execute(s.cfg); err != nil {
return err
}
return nil
}
+51
View File
@@ -0,0 +1,51 @@
package command
import (
"context"
"fmt"
"github.com/asim/go-micro/plugins/events/nats/v4"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/events/server"
"github.com/owncloud/ocis/audit/pkg/config"
"github.com/owncloud/ocis/audit/pkg/config/parser"
"github.com/owncloud/ocis/audit/pkg/logging"
svc "github.com/owncloud/ocis/audit/pkg/service"
"github.com/owncloud/ocis/audit/pkg/types"
"github.com/urfave/cli/v2"
)
// Server is the entrypoint 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 {
return parser.ParseConfig(cfg)
},
Action: func(c *cli.Context) error {
logger := logging.Configure(cfg.Service.Name, cfg.Log)
ctx := cfg.Context
if ctx == nil {
ctx = context.Background()
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
evtsCfg := cfg.Events
client, err := server.NewNatsStream(nats.Address(evtsCfg.Endpoint), nats.ClusterID(evtsCfg.Cluster))
if err != nil {
return err
}
evts, err := events.Consume(client, evtsCfg.ConsumerGroup, types.RegisteredEvents()...)
if err != nil {
return err
}
svc.AuditLoggerFromConfig(ctx, cfg.Auditlog, evts, logger)
return nil
},
}
}
+19
View File
@@ -0,0 +1,19 @@
package command
import (
"github.com/owncloud/ocis/audit/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 {
// not implemented
return nil
},
}
}
+37
View File
@@ -0,0 +1,37 @@
package config
import (
"context"
"github.com/owncloud/ocis/ocis-pkg/shared"
)
// Config combines all available configuration parts.
type Config struct {
*shared.Commons `ocisConfig:"-" yaml:"-"`
Service Service `ocisConfig:"-" yaml:"-"`
Log *Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
Events Events `ocisConfig:"events"`
Auditlog Auditlog `ocisConfig:"auditlog"`
Context context.Context `ocisConfig:"-" yaml:"-"`
}
// Events combines the configuration options for the event bus.
type Events struct {
Endpoint string `ocisConfig:"events_endpoint" env:"AUDIT_EVENTS_ENDPOINT" desc:"the address of the streaming service"`
Cluster string `ocisConfig:"events_cluster" env:"AUDIT_EVENTS_CLUSTER" desc:"the clusterID of the streaming service. Mandatory when using nats"`
ConsumerGroup string `ocisConfig:"events_group" env:"AUDIT_EVENTS_GROUP" desc:"the customergroup of the service. One group will only get one vopy of an event"`
}
// Auditlog holds audit log information
type Auditlog struct {
LogToConsole bool `ocisConfig:"log_to_console" env:"AUDIT_LOG_TO_CONSOLE" desc:"logs to Stdout if true"`
LogToFile bool `ocisConfig:"log_to_file" env:"AUDIT_LOG_TO_FILE" desc:"logs to file if true"`
FilePath string `ocisConfig:"filepath" env:"AUDIT_FILEPATH" desc:"filepath to the logfile. Mandatory if LogToFile is true"`
Format string `ocisConfig:"format" env:"AUDIT_FORMAT" desc:"log format. using json is advised"`
}
+9
View File
@@ -0,0 +1,9 @@
package config
// Debug defines the available debug configuration.
type Debug struct {
Addr string `ocisConfig:"addr" env:"AUDIT_DEBUG_ADDR"`
Token string `ocisConfig:"token" env:"AUDIT_DEBUG_TOKEN"`
Pprof bool `ocisConfig:"pprof" env:"AUDIT_DEBUG_PPROF"`
Zpages bool `ocisConfig:"zpages" env:"AUDIT_DEBUG_ZPAGES"`
}
+18
View File
@@ -0,0 +1,18 @@
package config
func DefaultConfig() *Config {
return &Config{
Service: Service{
Name: "audit",
},
Events: Events{
Endpoint: "127.0.0.1:9233",
Cluster: "test-cluster",
ConsumerGroup: "audit",
},
Auditlog: Auditlog{
LogToConsole: true,
Format: "json",
},
}
}
+9
View File
@@ -0,0 +1,9 @@
package config
// Log defines the available log configuration.
type Log struct {
Level string `mapstructure:"level" env:"OCIS_LOG_LEVEL;AUDIT_LOG_LEVEL"`
Pretty bool `mapstructure:"pretty" env:"OCIS_LOG_PRETTY;AUDIT_LOG_PRETTY"`
Color bool `mapstructure:"color" env:"OCIS_LOG_COLOR;AUDIT_LOG_COLOR"`
File string `mapstructure:"file" env:"OCIS_LOG_FILE;AUDIT_LOG_FILE"`
}
+40
View File
@@ -0,0 +1,40 @@
package parser
import (
"errors"
"github.com/owncloud/ocis/audit/pkg/config"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
)
// ParseConfig loads accounts configuration from known paths.
func ParseConfig(cfg *config.Config) error {
_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg)
if err != nil {
return err
}
// 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{}
}
// 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
}
}
return nil
}
+6
View File
@@ -0,0 +1,6 @@
package config
// Service defines the available service configuration.
type Service struct {
Name string `ocisConfig:"-" yaml:"-"`
}
+17
View File
@@ -0,0 +1,17 @@
package logging
import (
"github.com/owncloud/ocis/audit/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/log"
)
// 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),
)
}
+130
View File
@@ -0,0 +1,130 @@
package svc
import (
"context"
"encoding/json"
"fmt"
"os"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/owncloud/ocis/audit/pkg/config"
"github.com/owncloud/ocis/audit/pkg/types"
"github.com/owncloud/ocis/ocis-pkg/log"
)
// Log is used to log to different outputs
type Log func([]byte)
// Marshaller is used to marshal events
type Marshaller func(interface{}) ([]byte, error)
// AuditLoggerFromConfig will start a new AuditLogger generated from the config
func AuditLoggerFromConfig(ctx context.Context, cfg config.Auditlog, ch <-chan interface{}, log log.Logger) {
var logs []Log
if cfg.LogToConsole {
logs = append(logs, WriteToStdout())
}
if cfg.LogToFile {
logs = append(logs, WriteToFile(cfg.FilePath, log))
}
StartAuditLogger(ctx, ch, log, Marshal(cfg.Format, log), logs...)
}
// StartAuditLogger will block. run in seperate go routine
func StartAuditLogger(ctx context.Context, ch <-chan interface{}, log log.Logger, marshaller Marshaller, logto ...Log) {
for {
select {
case <-ctx.Done():
return
case i := <-ch:
var auditEvent interface{}
switch ev := i.(type) {
case events.ShareCreated:
auditEvent = types.ShareCreated(ev)
case events.LinkCreated:
auditEvent = types.LinkCreated(ev)
case events.ShareUpdated:
auditEvent = types.ShareUpdated(ev)
case events.LinkUpdated:
auditEvent = types.LinkUpdated(ev)
case events.ShareRemoved:
auditEvent = types.ShareRemoved(ev)
case events.LinkRemoved:
auditEvent = types.LinkRemoved(ev)
case events.ReceivedShareUpdated:
auditEvent = types.ReceivedShareUpdated(ev)
case events.LinkAccessed:
auditEvent = types.LinkAccessed(ev)
case events.LinkAccessFailed:
auditEvent = types.LinkAccessFailed(ev)
default:
log.Error().Interface("event", ev).Msg(fmt.Sprintf("can't handle event of type '%T'", ev))
continue
}
b, err := marshaller(auditEvent)
if err != nil {
log.Error().Err(err).Msg("error marshaling the event")
continue
}
for _, l := range logto {
l(b)
}
}
}
}
// WriteToFile returns a Log function writing to a file
func WriteToFile(path string, log log.Logger) Log {
return func(content []byte) {
file, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Error().Err(err).Msgf("error opening file '%s'", path)
return
}
defer file.Close()
if _, err := fmt.Fprintln(file, string(content)); err != nil {
log.Error().Err(err).Msgf("error writing to file '%s'", path)
}
}
}
// WriteToStdout return a Log function writing to Stdout
func WriteToStdout() Log {
return func(content []byte) {
fmt.Println(string(content))
}
}
// Marshal returns a Marshaller from the `format` string
func Marshal(format string, log log.Logger) Marshaller {
switch format {
default:
log.Error().Msgf("unknown format '%s'", format)
return nil
case "json":
return json.Marshal
case "minimal":
return func(ev interface{}) ([]byte, error) {
b, err := json.Marshal(ev)
if err != nil {
return nil, err
}
m := make(map[string]interface{})
if err := json.Unmarshal(b, &m); err != nil {
return nil, err
}
format := fmt.Sprintf("%s)\n %s", m["Action"], m["Message"])
return []byte(format), nil
}
}
}
+415
View File
@@ -0,0 +1,415 @@
package svc
import (
"context"
"encoding/json"
"testing"
"github.com/cs3org/reva/v2/pkg/events"
"github.com/owncloud/ocis/audit/pkg/types"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/test-go/testify/require"
group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
rtypes "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
)
var testCases = []struct {
Alias string
SystemEvent interface{}
CheckAuditEvent func(*testing.T, []byte)
}{
{
Alias: "ShareCreated - user",
SystemEvent: events.ShareCreated{
Sharer: userID("sharing-userid"),
GranteeUserID: userID("beshared-userid"),
GranteeGroupID: nil,
ItemID: resourceID("storage-1", "itemid-1"),
CTime: timestamp(0),
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareCreated{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "1970-01-01T00:00:00Z", "user 'sharing-userid' shared file 'itemid-1' with 'beshared-userid'", "file_shared")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "")
// AuditEventShareCreated fields
require.Equal(t, "", ev.ItemType)
require.Equal(t, "", ev.ExpirationDate)
require.Equal(t, false, ev.SharePass)
//require.Equal(t, "stat:true ", ev.Permissions) // TODO: BUG! Should work
require.Equal(t, "user", ev.ShareType)
require.Equal(t, "beshared-userid", ev.ShareWith)
require.Equal(t, "sharing-userid", ev.ShareOwner)
require.Equal(t, "", ev.ShareToken)
},
}, {
Alias: "ShareCreated - group",
SystemEvent: events.ShareCreated{
Sharer: userID("sharing-userid"),
GranteeUserID: nil,
GranteeGroupID: groupID("beshared-groupid"),
ItemID: resourceID("storage-1", "itemid-1"),
CTime: timestamp(10e8),
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareCreated{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "2001-09-09T01:46:40Z", "user 'sharing-userid' shared file 'itemid-1' with 'beshared-groupid'", "file_shared")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "")
// AuditEventShareCreated fields
require.Equal(t, "", ev.ItemType)
require.Equal(t, "", ev.ExpirationDate)
require.Equal(t, false, ev.SharePass)
//require.Equal(t, "stat:true ", ev.Permissions) // TODO: BUG! Should work
require.Equal(t, "group", ev.ShareType)
require.Equal(t, "beshared-groupid", ev.ShareWith)
require.Equal(t, "sharing-userid", ev.ShareOwner)
require.Equal(t, "", ev.ShareToken)
},
}, {
Alias: "ShareUpdated",
SystemEvent: events.ShareUpdated{
ShareID: shareID("shareid"),
Sharer: userID("sharing-userid"),
GranteeUserID: nil,
GranteeGroupID: groupID("beshared-groupid"),
ItemID: resourceID("storage-1", "itemid-1"),
Permissions: sharePermissions("stat", "get_quota"),
MTime: timestamp(10e8),
Updated: "permissions",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareUpdated{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "2001-09-09T01:46:40Z", "user 'sharing-userid' updated field 'permissions' of share 'shareid'", "share_permission_updated")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "", ev.ExpirationDate) // no expiration for shares
require.Equal(t, false, ev.SharePass)
require.Equal(t, "get_quota:true stat:true ", ev.Permissions)
require.Equal(t, "group", ev.ShareType)
require.Equal(t, "beshared-groupid", ev.ShareWith)
require.Equal(t, "sharing-userid", ev.ShareOwner)
require.Equal(t, "", ev.ShareToken) // token not filled for shares
},
}, {
Alias: "LinkUpdated - permissions",
SystemEvent: events.LinkUpdated{
ShareID: linkID("shareid"),
Sharer: userID("sharing-userid"),
ItemID: resourceID("storage-1", "itemid-1"),
Permissions: linkPermissions("stat"),
CTime: timestamp(10e8),
DisplayName: "link",
Expiration: timestamp(10e8 + 10e5),
PasswordProtected: true,
Token: "token-123",
FieldUpdated: "permissions",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareUpdated{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "2001-09-09T01:46:40Z", "user 'sharing-userid' updated field 'permissions' of public link 'shareid'", "share_permission_updated")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "2001-09-20T15:33:20Z", ev.ExpirationDate)
require.Equal(t, true, ev.SharePass)
require.Equal(t, "stat:true ", ev.Permissions)
require.Equal(t, "link", ev.ShareType)
require.Equal(t, "", ev.ShareWith) // not filled on links
require.Equal(t, "sharing-userid", ev.ShareOwner)
require.Equal(t, "token-123", ev.ShareToken)
},
}, {
Alias: "ShareRemoved",
SystemEvent: events.ShareRemoved{
ShareID: shareID("shareid"),
ShareKey: nil,
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareRemoved{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "", "", "share id:'shareid' uid:'' item-id:'' was removed", "file_unshared")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "", "", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "", ev.ShareType)
require.Equal(t, "", ev.ShareWith) // not filled on links
},
}, {
Alias: "LinkRemoved - id",
SystemEvent: events.LinkRemoved{
ShareID: linkID("shareid"),
ShareToken: "",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareRemoved{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "", "", "public link id:'shareid' was removed", "file_unshared")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "", "", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "link", ev.ShareType)
require.Equal(t, "", ev.ShareWith) // not filled on links
},
}, {
Alias: "LinkRemoved - token",
SystemEvent: events.LinkRemoved{
ShareID: nil,
ShareToken: "token-123",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventShareRemoved{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "", "", "public link id:'token-123' was removed", "file_unshared")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "", "", "token-123")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "link", ev.ShareType)
require.Equal(t, "", ev.ShareWith) // not filled on links
},
}, {
Alias: "Share accepted",
SystemEvent: events.ReceivedShareUpdated{
ShareID: shareID("shareid"),
ItemID: resourceID("storageid-1", "itemid-1"),
Permissions: sharePermissions("get_quota"),
GranteeUserID: userID("beshared-userid"),
GranteeGroupID: nil,
Sharer: userID("sharing-userid"),
MTime: timestamp(10e8),
State: "SHARE_STATE_ACCEPTED",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventReceivedShareUpdated{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "beshared-userid", "2001-09-09T01:46:40Z", "user 'beshared-userid' accepted share 'shareid' from user 'sharing-userid'", "share_accepted")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType)
require.Equal(t, "user", ev.ShareType)
require.Equal(t, "beshared-userid", ev.ShareWith)
},
}, {
Alias: "Share declined",
SystemEvent: events.ReceivedShareUpdated{
ShareID: shareID("shareid"),
ItemID: resourceID("storageid-1", "itemid-1"),
Permissions: sharePermissions("get_quota"),
GranteeUserID: userID("beshared-userid"),
GranteeGroupID: nil,
Sharer: userID("sharing-userid"),
MTime: timestamp(10e8),
State: "SHARE_STATE_DECLINED",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventReceivedShareUpdated{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "beshared-userid", "2001-09-09T01:46:40Z", "user 'beshared-userid' declined share 'shareid' from user 'sharing-userid'", "share_declined")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType)
require.Equal(t, "user", ev.ShareType)
require.Equal(t, "beshared-userid", ev.ShareWith)
},
}, {
Alias: "Link accessed - success",
SystemEvent: events.LinkAccessed{
ShareID: linkID("shareid"),
Sharer: userID("sharing-userid"),
ItemID: resourceID("storage-1", "itemid-1"),
Permissions: linkPermissions("stat"),
DisplayName: "link",
Expiration: timestamp(10e8 + 10e5),
PasswordProtected: true,
CTime: timestamp(10e8),
Token: "token-123",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventLinkAccessed{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "2001-09-09T01:46:40Z", "link 'shareid' was accessed. Success: true", "public_link_accessed")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "itemid-1", "sharing-userid", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "token-123", ev.ShareToken)
require.Equal(t, true, ev.Success)
},
}, {
Alias: "Link accessed - failure",
SystemEvent: events.LinkAccessFailed{
ShareID: linkID("shareid"),
Token: "token-123",
Status: 8,
Message: "access denied",
},
CheckAuditEvent: func(t *testing.T, b []byte) {
ev := types.AuditEventLinkAccessed{}
require.NoError(t, json.Unmarshal(b, &ev))
// AuditEvent fields
checkBaseAuditEvent(t, ev.AuditEvent, "", "", "link 'shareid' was accessed. Success: false", "public_link_accessed")
// AuditEventSharing fields
checkSharingAuditEvent(t, ev.AuditEventSharing, "", "", "shareid")
// AuditEventShareUpdated fields
require.Equal(t, "", ev.ItemType) // not implemented atm
require.Equal(t, "token-123", ev.ShareToken)
require.Equal(t, false, ev.Success)
},
},
}
func TestAuditLogging(t *testing.T) {
log := log.NewLogger()
inch := make(chan interface{})
defer close(inch)
outch := make(chan []byte)
defer close(outch)
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()
go StartAuditLogger(ctx, inch, log, Marshal("json", log), func(b []byte) {
outch <- b
})
for i := range testCases {
tc := testCases[i]
t.Run(tc.Alias, func(t *testing.T) {
inch <- tc.SystemEvent
tc.CheckAuditEvent(t, <-outch)
})
}
}
func checkBaseAuditEvent(t *testing.T, ev types.AuditEvent, user string, time string, message string, action string) {
require.Equal(t, "", ev.RemoteAddr) // not implemented atm
require.Equal(t, user, ev.User)
require.Equal(t, "", ev.URL) // not implemented atm
require.Equal(t, "", ev.Method) // not implemented atm
require.Equal(t, "", ev.UserAgent) // not implemented atm
require.Equal(t, time, ev.Time)
require.Equal(t, "admin_audit", ev.App)
require.Equal(t, message, ev.Message)
require.Equal(t, action, ev.Action)
require.Equal(t, false, ev.CLI) // not implemented atm
require.Equal(t, 1, ev.Level)
}
func checkSharingAuditEvent(t *testing.T, ev types.AuditEventSharing, itemID string, owner string, shareID string) {
require.Equal(t, itemID, ev.FileID)
require.Equal(t, owner, ev.Owner)
require.Equal(t, "", ev.Path) // not implemented atm
require.Equal(t, shareID, ev.ShareID)
}
func shareID(id string) *collaboration.ShareId {
return &collaboration.ShareId{
OpaqueId: id,
}
}
func linkID(id string) *link.PublicShareId {
return &link.PublicShareId{
OpaqueId: id,
}
}
func userID(id string) *user.UserId {
return &user.UserId{
OpaqueId: id,
Idp: "idp",
}
}
func groupID(id string) *group.GroupId {
return &group.GroupId{
OpaqueId: id,
Idp: "idp",
}
}
func resourceID(sid, oid string) *provider.ResourceId {
return &provider.ResourceId{
StorageId: sid,
OpaqueId: oid,
}
}
func timestamp(seconds uint64) *rtypes.Timestamp {
return &rtypes.Timestamp{
Seconds: seconds,
Nanos: 0,
}
}
func sharePermissions(perms ...string) *collaboration.SharePermissions {
return &collaboration.SharePermissions{
Permissions: permissions(perms...),
}
}
func linkPermissions(perms ...string) *link.PublicSharePermissions {
return &link.PublicSharePermissions{
Permissions: permissions(perms...),
}
}
func permissions(permissions ...string) *provider.ResourcePermissions {
perms := &provider.ResourcePermissions{}
for _, p := range permissions {
switch p {
case "stat":
perms.Stat = true
case "get_path":
perms.GetPath = true
case "list_container":
perms.ListContainer = true
case "get_quota":
perms.GetQuota = true
}
}
return perms
}
+61
View File
@@ -0,0 +1,61 @@
package types
import "fmt"
// short identifiers for audit actions
const (
ActionShareCreated = "file_shared"
ActionSharePermissionUpdated = "share_permission_updated"
ActionShareDisplayNameUpdated = "share_name_updated"
ActionSharePasswordUpdated = "share_password_updated"
ActionShareExpirationUpdated = "share_expiration_updated"
ActionShareRemoved = "file_unshared"
ActionShareAccepted = "share_accepted"
ActionShareDeclined = "share_declined"
ActionLinkAccessed = "public_link_accessed"
)
// MessageShareCreated returns the human readable string that describes the action
func MessageShareCreated(sharer, item, grantee string) string {
return fmt.Sprintf("user '%s' shared file '%s' with '%s'", sharer, item, grantee)
}
// MessageLinkCreated returns the human readable string that describes the action
func MessageLinkCreated(sharer, item, shareid string) string {
return fmt.Sprintf("user '%s' created a public to file '%s' with id '%s'", sharer, item, shareid)
}
// MessageShareUpdated returns the human readable string that describes the action
func MessageShareUpdated(sharer, shareID, fieldUpdated string) string {
return fmt.Sprintf("user '%s' updated field '%s' of share '%s'", sharer, fieldUpdated, shareID)
}
// MessageLinkUpdated returns the human readable string that describes the action
func MessageLinkUpdated(sharer, shareid, fieldUpdated string) string {
return fmt.Sprintf("user '%s' updated field '%s' of public link '%s'", sharer, fieldUpdated, shareid)
}
// MessageShareRemoved returns the human readable string that describes the action
func MessageShareRemoved(sharer, shareid, itemid string) string {
return fmt.Sprintf("share id:'%s' uid:'%s' item-id:'%s' was removed", shareid, sharer, itemid)
}
// MessageLinkRemoved returns the human readable string that describes the action
func MessageLinkRemoved(shareid string) string {
return fmt.Sprintf("public link id:'%s' was removed", shareid)
}
// MessageShareAccepted returns the human readable string that describes the action
func MessageShareAccepted(userid, shareid, sharerid string) string {
return fmt.Sprintf("user '%s' accepted share '%s' from user '%s'", userid, shareid, sharerid)
}
// MessageShareDeclined returns the human readable string that describes the action
func MessageShareDeclined(userid, shareid, sharerid string) string {
return fmt.Sprintf("user '%s' declined share '%s' from user '%s'", userid, shareid, sharerid)
}
// MessageLinkAccessed returns the human readable string that describes the action
func MessageLinkAccessed(linkid string, success bool) string {
return fmt.Sprintf("link '%s' was accessed. Success: %v", linkid, success)
}
+259
View File
@@ -0,0 +1,259 @@
package types
import (
"fmt"
"time"
"github.com/cs3org/reva/v2/pkg/events"
group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
)
// BasicAuditEvent creates an AuditEvent from given values
func BasicAuditEvent(uid string, ctime string, msg string, action string) AuditEvent {
return AuditEvent{
User: uid,
Time: ctime,
App: "admin_audit",
Message: msg,
Action: action,
Level: 1,
// NOTE: those values are not in the events and can therefore not be filled at the moment
RemoteAddr: "",
URL: "",
Method: "",
UserAgent: "",
CLI: false,
}
}
// SharingAuditEvent creates an AuditEventSharing from given values
func SharingAuditEvent(shareid string, fileid string, uid string, base AuditEvent) AuditEventSharing {
return AuditEventSharing{
AuditEvent: base,
FileID: fileid,
Owner: uid,
ShareID: shareid,
// NOTE: those values are not in the events and can therefore not be filled at the moment
Path: "",
}
}
// ShareCreated converts a ShareCreated Event to an AuditEventShareCreated
func ShareCreated(ev events.ShareCreated) AuditEventShareCreated {
uid := ev.Sharer.OpaqueId
with, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID)
base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageShareCreated(uid, ev.ItemID.OpaqueId, with), ActionShareCreated)
return AuditEventShareCreated{
AuditEventSharing: SharingAuditEvent("", ev.ItemID.OpaqueId, uid, base),
ShareOwner: uid,
ShareWith: with,
ShareType: typ,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
ExpirationDate: "",
SharePass: false,
Permissions: "",
ShareToken: "",
}
}
// LinkCreated converts a ShareCreated Event to an AuditEventShareCreated
func LinkCreated(ev events.LinkCreated) AuditEventShareCreated {
uid := ev.Sharer.OpaqueId
with, typ := "", "link"
base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageLinkCreated(uid, ev.ItemID.OpaqueId, ev.ShareID.OpaqueId), ActionShareCreated)
return AuditEventShareCreated{
AuditEventSharing: SharingAuditEvent("", ev.ItemID.OpaqueId, uid, base),
ShareOwner: uid,
ShareWith: with,
ShareType: typ,
ExpirationDate: formatTime(ev.Expiration),
SharePass: ev.PasswordProtected,
Permissions: ev.Permissions.String(),
ShareToken: ev.Token,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
// ShareUpdated converts a ShareUpdated event to an AuditEventShareUpdated
func ShareUpdated(ev events.ShareUpdated) AuditEventShareUpdated {
uid := ev.Sharer.OpaqueId
with, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID)
base := BasicAuditEvent(uid, formatTime(ev.MTime), MessageShareUpdated(uid, ev.ShareID.OpaqueId, ev.Updated), updateType(ev.Updated))
return AuditEventShareUpdated{
AuditEventSharing: SharingAuditEvent(ev.ShareID.GetOpaqueId(), ev.ItemID.OpaqueId, uid, base),
ShareOwner: uid,
ShareWith: with,
ShareType: typ,
Permissions: ev.Permissions.Permissions.String(),
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
ExpirationDate: "",
SharePass: false,
ShareToken: "",
}
}
// LinkUpdated converts a LinkUpdated event to an AuditEventShareUpdated
func LinkUpdated(ev events.LinkUpdated) AuditEventShareUpdated {
uid := ev.Sharer.OpaqueId
with, typ := "", "link"
base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageLinkUpdated(uid, ev.ShareID.OpaqueId, ev.FieldUpdated), updateType(ev.FieldUpdated))
return AuditEventShareUpdated{
AuditEventSharing: SharingAuditEvent(ev.ShareID.GetOpaqueId(), ev.ItemID.OpaqueId, uid, base),
ShareOwner: uid,
ShareWith: with,
ShareType: typ,
Permissions: ev.Permissions.Permissions.String(),
ExpirationDate: formatTime(ev.Expiration),
SharePass: ev.PasswordProtected,
ShareToken: ev.Token,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
// ShareRemoved converts a ShareRemoved event to an AuditEventShareRemoved
func ShareRemoved(ev events.ShareRemoved) AuditEventShareRemoved {
sid, uid, iid, with, typ := "", "", "", "", ""
if ev.ShareID != nil {
sid = ev.ShareID.GetOpaqueId()
}
if ev.ShareKey != nil {
uid = ev.ShareKey.GetOwner().GetOpaqueId()
iid = ev.ShareKey.GetResourceId().GetOpaqueId()
with, typ = extractGrantee(ev.ShareKey.GetGrantee().GetUserId(), ev.ShareKey.GetGrantee().GetGroupId())
}
base := BasicAuditEvent(uid, "", MessageShareRemoved(uid, sid, iid), ActionShareRemoved)
return AuditEventShareRemoved{
AuditEventSharing: SharingAuditEvent(sid, iid, uid, base),
ShareWith: with,
ShareType: typ,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
// LinkRemoved converts a LinkRemoved event to an AuditEventShareRemoved
func LinkRemoved(ev events.LinkRemoved) AuditEventShareRemoved {
uid, sid, typ := "", "", "link"
if ev.ShareID != nil {
sid = ev.ShareID.GetOpaqueId()
} else {
sid = ev.ShareToken
}
base := BasicAuditEvent(uid, "", MessageLinkRemoved(sid), ActionShareRemoved)
return AuditEventShareRemoved{
AuditEventSharing: SharingAuditEvent(sid, "", uid, base),
ShareWith: "",
ShareType: typ,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
// ReceivedShareUpdated converts a ReceivedShareUpdated event to an AuditEventReceivedShareUpdated
func ReceivedShareUpdated(ev events.ReceivedShareUpdated) AuditEventReceivedShareUpdated {
uid := ev.Sharer.GetOpaqueId()
sid := ev.ShareID.GetOpaqueId()
with, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID)
itemID := ev.ItemID.GetOpaqueId()
msg, utype := "", ""
switch ev.State {
case "SHARE_STATE_ACCEPTED":
msg = MessageShareAccepted(with, sid, uid)
utype = ActionShareAccepted
case "SHARE_STATE_DECLINED":
msg = MessageShareDeclined(with, sid, uid)
utype = ActionShareDeclined
}
base := BasicAuditEvent(with, formatTime(ev.MTime), msg, utype)
return AuditEventReceivedShareUpdated{
AuditEventSharing: SharingAuditEvent(sid, itemID, uid, base),
ShareType: typ,
ShareWith: with,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
// LinkAccessed converts a LinkAccessed event to an AuditEventLinkAccessed
func LinkAccessed(ev events.LinkAccessed) AuditEventLinkAccessed {
uid := ev.Sharer.OpaqueId
base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageLinkAccessed(ev.ShareID.GetOpaqueId(), true), ActionLinkAccessed)
return AuditEventLinkAccessed{
AuditEventSharing: SharingAuditEvent(ev.ShareID.GetOpaqueId(), ev.ItemID.OpaqueId, uid, base),
ShareToken: ev.Token,
Success: true,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
// LinkAccessFailed converts a LinkAccessFailed event to an AuditEventLinkAccessed
func LinkAccessFailed(ev events.LinkAccessFailed) AuditEventLinkAccessed {
base := BasicAuditEvent("", "", MessageLinkAccessed(ev.ShareID.GetOpaqueId(), false), ActionLinkAccessed)
return AuditEventLinkAccessed{
AuditEventSharing: SharingAuditEvent(ev.ShareID.GetOpaqueId(), "", "", base),
ShareToken: ev.Token,
Success: false,
// NOTE: those values are not in the event and can therefore not be filled at the moment
ItemType: "",
}
}
func extractGrantee(uid *user.UserId, gid *group.GroupId) (string, string) {
switch {
case uid != nil && uid.OpaqueId != "":
return uid.OpaqueId, "user"
case gid != nil && gid.OpaqueId != "":
return gid.OpaqueId, "group"
}
return "", ""
}
func formatTime(t *types.Timestamp) string {
if t == nil {
return ""
}
return time.Unix(int64(t.Seconds), int64(t.Nanos)).UTC().Format(time.RFC3339)
}
func updateType(u string) string {
switch {
case u == "permissions":
return ActionSharePermissionUpdated
case u == "displayname":
return ActionShareDisplayNameUpdated
case u == "TYPE_PERMISSIONS":
return ActionSharePermissionUpdated
case u == "TYPE_DISPLAYNAME":
return ActionShareDisplayNameUpdated
case u == "TYPE_PASSWORD":
return ActionSharePasswordUpdated
case u == "TYPE_EXPIRATION":
return ActionShareExpirationUpdated
default:
fmt.Println("Unknown update type", u)
return ""
}
}
+20
View File
@@ -0,0 +1,20 @@
package types
import (
"github.com/cs3org/reva/v2/pkg/events"
)
// RegisteredEvents returns the events the service is registered for
func RegisteredEvents() []events.Unmarshaller {
return []events.Unmarshaller{
events.ShareCreated{},
events.ShareUpdated{},
events.LinkCreated{},
events.LinkUpdated{},
events.ShareRemoved{},
events.LinkRemoved{},
events.ReceivedShareUpdated{},
events.LinkAccessed{},
events.LinkAccessFailed{},
}
}
+78
View File
@@ -0,0 +1,78 @@
package types
// AuditEvent is the basic audit event
type AuditEvent struct {
RemoteAddr string // the remote client IP
User string // the UID of the user performing the action. Or "IP x.x.x.x.", "cron", "CLI", "unknown"
URL string // the process request URI
Method string // the HTTP request method
UserAgent string // the HTTP request user agent
Time string // the time of the event eg: 2018-05-08T08:26:00+00:00
App string // always 'admin_audit'
Message string // sentence explaining the action
Action string // unique action identifier eg: file_delete or public_link_created
CLI bool // if the action was performed from the CLI
Level int // the log level of the entry (usually 1 for audit events)
}
// AuditEventSharing is the basic audit event for shares
type AuditEventSharing struct {
AuditEvent
FileID string // The file identifier for the item shared.
Owner string // The UID of the owner of the shared item.
Path string // The path to the shared item.
ShareID string // The sharing identifier. (not available for public_link_accessed or when recipient unshares)
}
// AuditEventShareCreated is the event logged when a share is created
type AuditEventShareCreated struct {
AuditEventSharing
ItemType string // file or folder
ExpirationDate string // The text expiration date in format 'yyyy-mm-dd'
SharePass bool // If the share is password protected.
Permissions string // The permissions string eg: "READ"
ShareType string // group user or link
ShareWith string // The UID or GID of the share recipient. (not available for public link)
ShareOwner string // The UID of the share owner.
ShareToken string // For link shares the unique token, else null
}
// AuditEventShareUpdated is the event logged when a share is updated
type AuditEventShareUpdated struct {
AuditEventSharing
ItemType string // file or folder
ExpirationDate string // The text expiration date in format 'yyyy-mm-dd'
SharePass bool // If the share is password protected.
Permissions string // The permissions string eg: "READ"
ShareType string // group user or link
ShareWith string // The UID or GID of the share recipient. (not available for public link)
ShareOwner string // The UID of the share owner.
ShareToken string // For link shares the unique token, else null
}
// AuditEventShareRemoved is the event logged when a share is removed
type AuditEventShareRemoved struct {
AuditEventSharing
ItemType string // file or folder
ShareType string // group user or link
ShareWith string // The UID or GID of the share recipient.
}
// AuditEventReceivedShareUpdated is the event logged when a share is accepted or declined
type AuditEventReceivedShareUpdated struct {
AuditEventSharing
ItemType string // file or folder
ShareType string // group user or link
ShareWith string // The UID or GID of the share recipient.
}
// AuditEventLinkAccessed is the event logged when a link is accessed
type AuditEventLinkAccessed struct {
AuditEventSharing
ShareToken string // The share token.
Success bool // If the request was successful.
ItemType string // file or folder
}
@@ -0,0 +1,5 @@
Bugfix: Network configuration in individiual_services example
Tidy up the deployments/examples/ocis_individual_services example so that the instructions work.
https://github.com/owncloud/ocis/pull/3238
+5
View File
@@ -0,0 +1,5 @@
Bugfix: Improve gif thumbnails
Improved the gif thumbnail generation for gifs with different disposal strategies.
https://github.com/owncloud/ocis/pull/3305
@@ -0,0 +1,5 @@
Enhancement: log sharing events in audit service
Contains sharing related events. See full list in audit/pkg/types/events.go
https://github.com/owncloud/ocis/pull/3301
+7
View File
@@ -0,0 +1,7 @@
Enhancement: Improve thumbnails API
Changed the thumbnails API to no longer transfer images via GRPC.
GRPC has a limited message size and isn't very efficient with large binary data.
The new API transports the images over HTTP.
https://github.com/owncloud/ocis/pull/3272
@@ -0,0 +1,9 @@
Enhancement: Update ownCloud Web to v5.3.0-rc.1
Tags: web
We updated ownCloud Web to v5.3.0-rc.1. Please refer to the changelog (linked) for details on the web release.
https://github.com/owncloud/web/pull/6561
https://github.com/owncloud/ocis/pull/3291
https://github.com/owncloud/web/releases/tag/v5.3.0-rc.1
@@ -47,7 +47,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- proxy
@@ -90,7 +90,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- nats-server
@@ -111,7 +111,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- /bin/sh
- /entrypoint-override.sh
@@ -145,7 +145,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- glauth
@@ -168,7 +168,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- idp
@@ -194,7 +194,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- ocs
@@ -222,7 +222,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- settings
@@ -247,7 +247,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- store
@@ -269,7 +269,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- thumbnails
@@ -296,7 +296,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- web
@@ -320,7 +320,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- webdav
@@ -343,7 +343,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- graph
@@ -369,7 +369,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-metadata
@@ -402,7 +402,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-auth-basic
@@ -426,7 +426,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-auth-machine
@@ -450,7 +450,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-auth-bearer
@@ -474,7 +474,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-shares
@@ -501,7 +501,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-users
@@ -535,7 +535,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-public-link
@@ -559,7 +559,7 @@ services:
deploy:
replicas: 1
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-sharing
@@ -592,7 +592,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-userprovider
@@ -623,7 +623,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-groupprovider
@@ -654,7 +654,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-frontend
@@ -684,7 +684,7 @@ services:
deploy:
replicas: ${OCIS_SCALE:-1}
networks:
ocis-net: null
ocis-net:
entrypoint:
- ocis
- storage-gateway
@@ -731,4 +731,3 @@ volumes:
networks:
ocis-net:
external: true
+1
View File
@@ -1 +1,2 @@
*_configvars.md
*-example.yaml
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/accounts-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/accounts_configvars.md" >}}
+16
View File
@@ -0,0 +1,16 @@
---
title: Audit
date: 2022-03-02T00:00:00+00:00
weight: 20
geekdocRepo: https://github.com/owncloud/ocis
geekdocEditPath: edit/master/docs/extensions/audit
geekdocFilePath: _index.md
geekdocCollapseSection: true
---
## Abstract
## Table of Contents
{{< toc-tree >}}
+12
View File
@@ -0,0 +1,12 @@
---
title: Service Configuration
date: 2018-05-02T00:00:00+00:00
weight: 20
geekdocRepo: https://github.com/owncloud/ocis
geekdocEditPath: edit/master/docs/extensions/audit
geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
{{< include file="extensions/_includes/audit_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/glauth-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/glauth_configvars.md" >}}
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/graph-explorer-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/graph-explorer_configvars.md" >}}
+2
View File
@@ -7,6 +7,8 @@ geekdocEditPath: edit/master/docs/extensions/graph
geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/graph-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/graph_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/idm-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/idm_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/idp-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/idp_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/nats-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/nats_configvars.md" >}}
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/notifications-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/notifications_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/ocs-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/ocs_configvars.md" >}}
+200
View File
@@ -0,0 +1,200 @@
---
title: Port Ranges
date: 2018-05-02T00:00:00+00:00
weight: 0
geekdocRepo: https://github.com/owncloud/ocis
geekdocEditPath: edit/master/docs/extensions
geekdocFilePath: port-ranges.go
geekdocCollapseSection: true
---
oCIS extensions often need a port to expose their services to other services or the outside world.
As users may have many different extensions running on the same machine, we should track port usage in the oCIS ecosystem. In the best case we ensure that each extension uses a non colliding port range, to make life of users easier.
This page tracks the knowingly used port ranges.
Feel free to "reserve" a free port range when you're developing an extension by adding your extension to the list (see the edit button in the top right corner).
If you're developing a non-public extension, we recommend using ports outside of the ranges listed below.
We also suggest to use the last port in your extensions' range as a debug/metrics port.
## Allocations
| Port range | Service |
| ---------- | ----------------------------------------------------------------------------- |
| 9000-9010 | [ocis](https://github.com/owncloud/ocis) |
| 9100-9104 | [web](https://github.com/owncloud/ocis/tree/master/web) |
| 9105-9109 | [hello](https://github.com/owncloud/ocis-hello) |
| 9110-9114 | [ocs](https://github.com/owncloud/ocis/tree/master/ocs) |
| 9115-9119 | [webdav](https://github.com/owncloud/ocis/tree/master/webdav) |
| 9120-9124 | [graph](https://github.com/owncloud/ocis/tree/master/graph) |
| 9125-9129 | [glauth](https://github.com/owncloud/ocis/tree/master/devldap) |
| 9130-9134 | [konnectd](https://github.com/owncloud/ocis/tree/master/konnectd) |
| 9135-9139 | [graph-explorer](https://github.com/owncloud/ocis/tree/master/graph-explorer) |
| 9140-9179 | [reva/storage](https://github.com/owncloud/ocis/tree/master/storage) |
| 9180-9184 | [accounts](https://github.com/owncloud/ocis/tree/master/accounts) |
| 9185-9189 | [thumbnails](https://github.com/owncloud/ocis/tree/master/thumbnails) |
| 9190-9194 | [settings](https://github.com/owncloud/ocis/tree/master/settings) |
| 9195-9199 | [store](https://github.com/owncloud/ocis/tree/master/store) |
| 9200-9204 | [proxy](https://github.com/owncloud/ocis/tree/master/proxy) |
| 9205-9209 | [markdown-editor](https://github.com/owncloud/ocis-markdown-editor) |
| 9210-9214 | [reva](https://github.com/owncloud/ocis-reva) unused? |
| 9215-9219 | reva metadata storage |
| 9220-9224 | FREE |
| 9225-9229 | photoprism (state: PoC) |
| 9230-9234 | [nats](https://github.com/owncloud/ocis/tree/master/nats) |
| 9235-9239 | idm TBD |
| 9240-9244 | FREE |
| 9245-9249 | FREE |
| 9250-9254 | oCIS Runtime |
| 9255-9259 | FREE |
| 9260-9264 | FREE |
| 9265-9269 | FREE |
| 9270-9274 | FREE |
| 9275-9279 | FREE |
| 9280-9284 | FREE |
| 9285-9289 | FREE |
| 9290-9294 | FREE |
| 9295-9299 | FREE |
| 9300-9304 | FREE |
| 9305-9309 | FREE |
| 9310-9314 | FREE |
| 9315-9319 | FREE |
| 9320-9324 | FREE |
| 9325-9329 | FREE |
| 9330-9334 | FREE |
| 9335-9339 | FREE |
| 9340-9344 | FREE |
| 9345-9349 | FREE |
| 9350-9354 | FREE |
| 9355-9359 | FREE |
| 9360-9364 | FREE |
| 9365-9369 | FREE |
| 9370-9374 | FREE |
| 9375-9379 | FREE |
| 9380-9384 | FREE |
| 9385-9389 | FREE |
| 9390-9394 | FREE |
| 9395-9399 | FREE |
| 9400-9404 | FREE |
| 9405-9409 | FREE |
| 9410-9414 | FREE |
| 9415-9419 | FREE |
| 9420-9424 | FREE |
| 9425-9429 | FREE |
| 9430-9434 | FREE |
| 9435-9439 | FREE |
| 9440-9444 | FREE |
| 9445-9449 | FREE |
| 9450-9454 | FREE |
| 9455-9459 | FREE |
| 9460-9464 | FREE |
| 9465-9469 | FREE |
| 9470-9474 | FREE |
| 9475-9479 | FREE |
| 9480-9484 | FREE |
| 9485-9489 | FREE |
| 9490-9494 | FREE |
| 9495-9499 | FREE |
| 9500-9504 | FREE |
| 9505-9509 | FREE |
| 9510-9514 | FREE |
| 9515-9519 | FREE |
| 9520-9524 | FREE |
| 9525-9529 | FREE |
| 9530-9534 | FREE |
| 9535-9539 | FREE |
| 9540-9544 | FREE |
| 9545-9549 | FREE |
| 9550-9554 | FREE |
| 9555-9559 | FREE |
| 9560-9564 | FREE |
| 9565-9569 | FREE |
| 9570-9574 | FREE |
| 9575-9579 | FREE |
| 9580-9584 | FREE |
| 9585-9589 | FREE |
| 9590-9594 | FREE |
| 9595-9599 | FREE |
| 9600-9604 | FREE |
| 9605-9609 | FREE |
| 9610-9614 | FREE |
| 9615-9619 | FREE |
| 9620-9624 | FREE |
| 9625-9629 | FREE |
| 9630-9634 | FREE |
| 9635-9639 | FREE |
| 9640-9644 | FREE |
| 9645-9649 | FREE |
| 9650-9654 | FREE |
| 9655-9659 | FREE |
| 9660-9664 | FREE |
| 9665-9669 | FREE |
| 9670-9674 | FREE |
| 9675-9679 | FREE |
| 9680-9684 | FREE |
| 9685-9689 | FREE |
| 9690-9694 | FREE |
| 9695-9699 | FREE |
| 9700-9704 | FREE |
| 9705-9709 | FREE |
| 9710-9714 | FREE |
| 9715-9719 | FREE |
| 9720-9724 | FREE |
| 9725-9729 | FREE |
| 9730-9734 | FREE |
| 9735-9739 | FREE |
| 9740-9744 | FREE |
| 9745-9749 | FREE |
| 9750-9754 | FREE |
| 9755-9759 | FREE |
| 9760-9764 | FREE |
| 9765-9769 | FREE |
| 9770-9774 | FREE |
| 9775-9779 | FREE |
| 9780-9784 | FREE |
| 9785-9789 | FREE |
| 9790-9794 | FREE |
| 9795-9799 | FREE |
| 9800-9804 | FREE |
| 9805-9809 | FREE |
| 9810-9814 | FREE |
| 9815-9819 | FREE |
| 9820-9824 | FREE |
| 9825-9829 | FREE |
| 9830-9834 | FREE |
| 9835-9839 | FREE |
| 9840-9844 | FREE |
| 9845-9849 | FREE |
| 9850-9854 | FREE |
| 9855-9859 | FREE |
| 9860-9864 | FREE |
| 9865-9869 | FREE |
| 9870-9874 | FREE |
| 9875-9879 | FREE |
| 9880-9884 | FREE |
| 9885-9889 | FREE |
| 9890-9894 | FREE |
| 9895-9899 | FREE |
| 9900-9904 | FREE |
| 9905-9909 | FREE |
| 9910-9914 | FREE |
| 9915-9919 | FREE |
| 9920-9924 | FREE |
| 9925-9929 | FREE |
| 9930-9934 | FREE |
| 9935-9939 | FREE |
| 9940-9944 | FREE |
| 9945-9949 | FREE |
| 9950-9954 | FREE |
| 9955-9959 | FREE |
| 9960-9964 | FREE |
| 9965-9969 | FREE |
| 9970-9974 | FREE |
| 9975-9979 | FREE |
| 9980-9984 | FREE |
| 9985-9989 | FREE |
| 9990-9994 | FREE |
| 9995-9999 | FREE |
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/proxy-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/proxy_configvars.md" >}}
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/settings-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/settings_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/store-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/store_configvars.md" >}}
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/thumbnails-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/thumbnails_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/web-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/web_configvars.md" >}}
+3
View File
@@ -8,5 +8,8 @@ geekdocFilePath: configuration.md
geekdocCollapseSection: true
---
## Example YAML Config
{{< include file="extensions/_includes/webdav-config-example.yaml" language="yaml" >}}
{{< include file="extensions/_includes/webdav_configvars.md" >}}
+26 -11
View File
@@ -6,14 +6,20 @@ import (
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"text/template"
)
var targets = map[string]string{
"example-config-generator.go.tmpl": "output/exampleconfig/example-config-generator.go",
"extractor.go.tmpl": "output/env/runner.go",
}
func main() {
fmt.Println("Getting relevant packages")
paths, err := filepath.Glob("../../*/pkg/config/defaultconfig.go")
paths, err := filepath.Glob("../../*/pkg/config/defaults/defaultconfig.go")
if err != nil {
log.Fatal(err)
}
@@ -24,27 +30,36 @@ func main() {
for i := range paths {
paths[i] = replacer.Replace(paths[i])
}
content, err := ioutil.ReadFile("extractor.go.tmpl")
for template, output := range targets {
GenerateIntermediateCode(template, output, paths)
RunIntermediateCode(output)
}
fmt.Println("Cleaning up")
os.RemoveAll("output")
}
func GenerateIntermediateCode(templatePath string, intermediateCodePath string, paths []string) {
content, err := ioutil.ReadFile(templatePath)
if err != nil {
log.Fatal(err)
}
fmt.Println("Generating intermediate go code")
fmt.Println("Generating intermediate go code for " + intermediateCodePath + " using template " + templatePath)
tpl := template.Must(template.New("").Parse(string(content)))
os.Mkdir("output", 0700)
runner, err := os.Create("output/runner.go")
os.MkdirAll(path.Dir(intermediateCodePath), 0700)
runner, err := os.Create(intermediateCodePath)
if err != nil {
log.Fatal(err)
}
tpl.Execute(runner, paths)
fmt.Println("Running intermediate go code")
os.Chdir("output")
}
func RunIntermediateCode(intermediateCodePath string) {
fmt.Println("Running intermediate go code for " + intermediateCodePath)
os.Setenv("OCIS_BASE_DATA_PATH", "~/.ocis")
out, err := exec.Command("go", "run", "runner.go").Output()
out, err := exec.Command("go", "run", intermediateCodePath).Output()
if err != nil {
log.Fatal(err)
}
fmt.Println(string(out))
fmt.Println("Cleaning up")
os.Chdir("../")
os.RemoveAll("output")
}
@@ -0,0 +1,53 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v2"
{{- range $key, $value := .}}
pkg{{$key}} "{{$value}}"
{{- end}}
)
func main() {
replacer := strings.NewReplacer(
"github.com/owncloud/ocis/", "",
"/pkg/config/defaults", "",
)
cfg := map[string]string{
{{- range $key, $value := .}}
replacer.Replace("{{$value}}"): func() string {
fmt.Println("Generating example YAML config for {{ $value -}}")
c := pkg{{$key}}.DefaultConfig()
pkg{{$key}}.EnsureDefaults(c)
pkg{{$key}}.Sanitize(c)
yml, err := yaml.Marshal(c)
if err != nil {
log.Fatalf("Marshalling yaml for pkg0 failed: %s\n", err)
}
return "# Autogenerated\n" + string(yml)
}(),
{{- end}}
}
for pkg, yml := range cfg {
targetFolders := []string{
// TODO: comment in when it is clear how to commit this to the structure of the master|main branch
// filepath.Join("../../", pkg, "/config"),
"../../docs/extensions/_includes/",
}
for _, targetFolder := range targetFolders {
os.MkdirAll(targetFolder, 0700)
targetYamlFile, err := os.Create(filepath.Join(targetFolder, replacer.Replace(pkg) + "-config-example.yaml"))
if err != nil {
log.Fatalf("Failed to create target file for : %s", err)
}
defer targetYamlFile.Close()
targetYamlFile.WriteString(yml)
}
}
}
+3 -3
View File
@@ -23,13 +23,13 @@ type ConfigField struct {
func main() {
fmt.Println("Generating documentation for environment variables:")
content, err := ioutil.ReadFile("../../../docs/templates/CONFIGURATION.tmpl")
content, err := ioutil.ReadFile("../../docs/templates/CONFIGURATION.tmpl")
if err != nil {
log.Fatal(err)
}
replacer := strings.NewReplacer(
"github.com/owncloud/ocis/", "",
"/pkg/config", "",
"/pkg/config/defaults", "",
)
var fields []ConfigField
var targetFile *os.File
@@ -41,7 +41,7 @@ m := map[string]interface{}{
{{- end }}
}
targetFolder := "../../../docs/extensions/_includes/"
targetFolder := "../../docs/extensions/_includes/"
for pkg, conf := range m {
fields = GetAnnotatedVariables(conf)
if len(fields) > 0 {
+4 -2
View File
@@ -15,10 +15,12 @@ If you need to access oCIS running in a docker container, on a VM or a remote ma
## Start the oCIS fullstack server from binary
Upon first start of the oCIS fullstack server with `./bin/ocis server` it will generate a file `identifier-registration.yml` in the config folder in your current working directory. This file is used to configure the built-in identity provider and therefore contains the OpenID Connect issuer and also information about relying parties, for example ownCloud Web and our desktop and mobile applications.
Upon first start of the oCIS fullstack server with `./bin/ocis server` it will generate a directory tree skeleton in `$HOME/.ocis`. If that is already existing it will not be overwritten as it contains all relevant data for oCIS.
In `$HOME/.ocis/idp` is a file `identifier-registration.yaml`. It is used to configure the built-in identity provider and therefore contains the OpenID Connect issuer and also information about relying parties, for example ownCloud Web and our desktop and mobile applications.
{{< hint warning >}}
The `identifier-registration.yml` file will only be generated if it does not exist yet. If you want to change certain environment variables like `OCIS_URL`, please delete this file first before doing so. Otherwise your changes will not be applied correctly and you will run into errors.
The `identifier-registration.yaml` file will only be generated if it does not exist yet. If you want to change certain environment variables like `OCIS_URL`, please delete this file first before doing so. Otherwise your changes will not be applied correctly and you will run into errors.
{{< /hint >}}
{{< hint warning >}}
+4 -4
View File
@@ -92,9 +92,9 @@ basedn = "dc=ocis,dc=test" # base dn to construct
{{< hint >}}
There is a bug in the config merging for environment variables, cli flags and config files causing log settings not to be picked up from the config file when specifying `--extensions`. That is why I will
* configure most of the config in a file,
* configure most of the config in a file,
* adjust logging using `OCIS_LOG_*` environment variables and
* specify which extension to run using `ocis/bin/ocis server --extensions "comma, separated, list, of, extensions"`.
* specify which extension to run using `ocis/bin/ocis server --extensions "comma, separated, list, of, extensions"`.
{{< /hint >}}
#### Run it!
@@ -129,7 +129,7 @@ To configure LDAP to use our glauth we add this section to the config file:
```toml
[storage.reva.ldap]
idp = "https://ocis.ocis.test"
basedn = "dc=ocis,dc=test"
basedn = "dc=ocis,dc=test"
binddn = "cn=admin,dc=ocis,dc=test" # an admin user in your oc10
bindpassword = "secret"
userschema = { uid = "uid", displayname = "givenname" } # TODO make glauth return an ownclouduuid and displayname attribute
@@ -158,7 +158,7 @@ Please use `exit` or `Ctrl-D` to exit this program.
username: jfd
password: OK
>> whoami
id:<idp:"https://ocis.ocis.test" opaque_id:"jfd" type:USER_TYPE_PRIMARY > username:"jfd" mail:"jfd@butonic.de" display_name:"J\303\266rn" uid_number:99 gid_number:99
id:<idp:"https://ocis.ocis.test" opaque_id:"jfd" type:USER_TYPE_PRIMARY > username:"jfd" mail:"jfd@butonic.de" display_name:"J\303\266rn" uid_number:99 gid_number:99
>> exit
```
+8 -7
View File
@@ -16,12 +16,13 @@ To skip the generation of demo users, run the inital setup step with an addition
Following users are available in the demo set:
| username | password | email | role | groups |
| -------- | ------------- | -------------------- | ----- | ----------------------------------------------------------------------- |
| admin | admin | admin@example.org | admin | users |
| einstein | relativity | einstein@example.org | user | users, philosophy-haters, physics-lovers, sailing-lovers, violin-haters |
| marie | radioactivity | marie@example.org | user | users, physics-lovers, polonium-lovers, radium-lovers |
| moss | vista | moss@example.org | admin | users |
| richard | superfluidity | richard@example.org | user | users, philosophy-haters, physics-lovers, quantum-lovers |
| username | password | email | role | groups |
| --------- | ------------- | --------------------- | ------------------- | ----------------------------------------------------------------------- |
| admin | admin | admin@example.org | admin | users |
| einstein | relativity | einstein@example.org | user | users, philosophy-haters, physics-lovers, sailing-lovers, violin-haters |
| marie | radioactivity | marie@example.org | user | users, physics-lovers, polonium-lovers, radium-lovers |
| moss | vista | moss@example.org | admin | users |
| richard | superfluidity | richard@example.org | user | users, philosophy-haters, physics-lovers, quantum-lovers |
| katherine | gemini | katherine@example.org | user, space-manager | users, sailing-lovers, physics-lovers, quantum-lovers |
You may also want to run oCIS with only your custom users by [deleting the demo users]({{< ref "../deployment#delete-demo-users" >}}).
+2 -2
View File
@@ -4,11 +4,11 @@ import (
"os"
"github.com/owncloud/ocis/glauth/pkg/command"
"github.com/owncloud/ocis/glauth/pkg/config"
"github.com/owncloud/ocis/glauth/pkg/config/defaults"
)
func main() {
if err := command.Execute(config.DefaultConfig()); err != nil {
if err := command.Execute(defaults.DefaultConfig()); err != nil {
os.Exit(1)
}
}
+3 -3
View File
@@ -8,9 +8,9 @@ import (
// Config combines all available configuration parts.
type Config struct {
*shared.Commons
*shared.Commons `ocisConfig:"-" yaml:"-"`
Service Service
Service Service `ocisConfig:"-" yaml:"-"`
Tracing *Tracing `ocisConfig:"tracing"`
Log *Log `ocisConfig:"log"`
@@ -24,7 +24,7 @@ type Config struct {
RoleBundleUUID string `ocisConfig:"role_bundle_uuid" env:"GLAUTH_ROLE_BUNDLE_ID"`
Context context.Context
Context context.Context `ocisConfig:"-" yaml:"-"`
}
// Backend defined the available backend configuration.
-51
View File
@@ -1,51 +0,0 @@
package config
import (
"path"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)
func DefaultConfig() *Config {
return &Config{
Debug: Debug{
Addr: "127.0.0.1:9129",
},
Service: Service{
Name: "glauth",
},
Ldap: Ldap{
Enabled: true,
Addr: "127.0.0.1:9125",
Namespace: "com.owncloud.ldap",
},
Ldaps: Ldaps{
Enabled: true,
Addr: "127.0.0.1:9126",
Namespace: "com.owncloud.ldaps",
Cert: path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"),
Key: path.Join(defaults.BaseDataPath(), "ldap", "ldap.key"),
},
Backend: Backend{
Datastore: "accounts",
BaseDN: "dc=ocis,dc=test",
Insecure: false,
NameFormat: "cn",
GroupFormat: "ou",
Servers: nil,
SSHKeyAttr: "sshPublicKey",
UseGraphAPI: true,
},
Fallback: FallbackBackend{
Datastore: "",
BaseDN: "dc=ocis,dc=test",
Insecure: false,
NameFormat: "cn",
GroupFormat: "ou",
Servers: nil,
SSHKeyAttr: "sshPublicKey",
UseGraphAPI: true,
},
RoleBundleUUID: "71881883-1768-46bd-a24d-a356a2afdf7f", // BundleUUIDRoleAdmin
}
}
@@ -0,0 +1,90 @@
package defaults
import (
"path"
"github.com/owncloud/ocis/glauth/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)
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:9129",
},
Service: config.Service{
Name: "glauth",
},
Ldap: config.Ldap{
Enabled: true,
Addr: "127.0.0.1:9125",
Namespace: "com.owncloud.ldap",
},
Ldaps: config.Ldaps{
Enabled: true,
Addr: "127.0.0.1:9126",
Namespace: "com.owncloud.ldaps",
Cert: path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"),
Key: path.Join(defaults.BaseDataPath(), "ldap", "ldap.key"),
},
Backend: config.Backend{
Datastore: "accounts",
BaseDN: "dc=ocis,dc=test",
Insecure: false,
NameFormat: "cn",
GroupFormat: "ou",
Servers: nil,
SSHKeyAttr: "sshPublicKey",
UseGraphAPI: true,
},
Fallback: config.FallbackBackend{
Datastore: "",
BaseDN: "dc=ocis,dc=test",
Insecure: false,
NameFormat: "cn",
GroupFormat: "ou",
Servers: nil,
SSHKeyAttr: "sshPublicKey",
UseGraphAPI: true,
},
RoleBundleUUID: "71881883-1768-46bd-a24d-a356a2afdf7f", // BundleUUIDRoleAdmin
}
}
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{}
}
}
func Sanitize(cfg *config.Config) {
// nothing to santizie here atm
}
+1 -1
View File
@@ -4,5 +4,5 @@ package config
type Ldap struct {
Enabled bool `ocisConfig:"enabled" env:"GLAUTH_LDAP_ENABLED"`
Addr string `ocisConfig:"addr" env:"GLAUTH_LDAP_ADDR"`
Namespace string
Namespace string `ocisConfig:"-" yaml:"-"`
}
+1 -1
View File
@@ -4,7 +4,7 @@ package config
type Ldaps struct {
Enabled bool `ocisConfig:"enabled" env:"GLAUTH_LDAPS_ENABLED"`
Addr string `ocisConfig:"addr" env:"GLAUTH_LDAPS_ADDR"`
Namespace string
Namespace string `ocisConfig:"-" yaml:"-"`
Cert string `ocisConfig:"cert" env:"GLAUTH_LDAPS_CERT"`
Key string `ocisConfig:"key" env:"GLAUTH_LDAPS_KEY"`
}
+3 -24
View File
@@ -4,6 +4,7 @@ import (
"errors"
"github.com/owncloud/ocis/glauth/pkg/config"
"github.com/owncloud/ocis/glauth/pkg/config/defaults"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
@@ -16,29 +17,7 @@ func ParseConfig(cfg *config.Config) error {
return err
}
// 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{}
}
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"
@@ -48,6 +27,6 @@ func ParseConfig(cfg *config.Config) error {
}
// sanitize config
defaults.Sanitize(cfg)
return nil
}
+1 -1
View File
@@ -2,5 +2,5 @@ package config
// Service defines the available service configuration.
type Service struct {
Name string
Name string `ocisConfig:"-" yaml:"-"`
}
+2 -1
View File
@@ -22,7 +22,7 @@ require (
github.com/blevesearch/bleve/v2 v2.3.1
github.com/coreos/go-oidc/v3 v3.1.0
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19
github.com/cs3org/reva/v2 v2.0.0-20220308091509-e4509f177c98
github.com/cs3org/reva/v2 v2.0.0-20220314085001-8e5b22a20a3f
github.com/disintegration/imaging v1.6.2
github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733
github.com/go-chi/chi/v5 v5.0.7
@@ -61,6 +61,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.7.0
github.com/test-go/testify v1.1.4
github.com/thejerf/suture/v4 v4.0.2
github.com/urfave/cli/v2 v2.3.0
go-micro.dev/v4 v4.6.0
+2 -2
View File
@@ -342,8 +342,8 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ=
github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/reva/v2 v2.0.0-20220308091509-e4509f177c98 h1:yttz8BjGwdmI/sd81Xretzpss/wXnnmCsdJWDOiZfWs=
github.com/cs3org/reva/v2 v2.0.0-20220308091509-e4509f177c98/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0=
github.com/cs3org/reva/v2 v2.0.0-20220314085001-8e5b22a20a3f h1:tv7v6OjbFoDFNB2ikGC+LLaWEOIAJnrZjyO5LRTDL0g=
github.com/cs3org/reva/v2 v2.0.0-20220314085001-8e5b22a20a3f/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
+2 -2
View File
@@ -4,11 +4,11 @@ import (
"os"
"github.com/owncloud/ocis/graph-explorer/pkg/command"
"github.com/owncloud/ocis/graph-explorer/pkg/config"
"github.com/owncloud/ocis/graph-explorer/pkg/config/defaults"
)
func main() {
if err := command.Execute(config.DefaultConfig()); err != nil {
if err := command.Execute(defaults.DefaultConfig()); err != nil {
os.Exit(1)
}
}
+3 -3
View File
@@ -8,9 +8,9 @@ import (
// Config combines all available configuration parts.
type Config struct {
*shared.Commons
*shared.Commons `ocisConfig:"-" yaml:"-"`
Service Service
Service Service `ocisConfig:"-" yaml:"-"`
Tracing *Tracing `ocisConfig:"tracing"`
Log *Log `ocisConfig:"log"`
@@ -20,7 +20,7 @@ type Config struct {
GraphExplorer GraphExplorer `ocisConfig:"graph_explorer"`
Context context.Context
Context context.Context `ocisConfig:"-" yaml:"-"`
}
// GraphExplorer defines the available graph-explorer configuration.
@@ -1,26 +0,0 @@
package config
func DefaultConfig() *Config {
return &Config{
Debug: Debug{
Addr: "127.0.0.1:9136",
Token: "",
Pprof: false,
Zpages: false,
},
HTTP: HTTP{
Addr: "127.0.0.1:9135",
Root: "/graph-explorer",
Namespace: "com.owncloud.web",
},
Service: Service{
Name: "graph-explorer",
},
GraphExplorer: GraphExplorer{
ClientID: "ocis-explorer.js",
Issuer: "https://localhost:9200",
GraphURLBase: "https://localhost:9200",
GraphURLPath: "/graph",
},
}
}
@@ -0,0 +1,73 @@
package defaults
import (
"strings"
"github.com/owncloud/ocis/graph-explorer/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:9136",
Token: "",
Pprof: false,
Zpages: false,
},
HTTP: config.HTTP{
Addr: "127.0.0.1:9135",
Root: "/graph-explorer",
Namespace: "com.owncloud.web",
},
Service: config.Service{
Name: "graph-explorer",
},
GraphExplorer: config.GraphExplorer{
ClientID: "ocis-explorer.js",
Issuer: "https://localhost:9200",
GraphURLBase: "https://localhost:9200",
GraphURLPath: "/graph",
},
}
}
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{}
}
}
func Sanitize(cfg *config.Config) {
// sanitize config
if cfg.HTTP.Root == "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/graph-explorer")
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ package config
type HTTP struct {
Addr string `ocisConfig:"addr" env:"GRAPH_EXPLORER_HTTP_ADDR"`
Root string `ocisConfig:"root" env:"GRAPH_EXPLORER_HTTP_ROOT"`
Namespace string
Namespace string `ocisConfig:"-" yaml:"-"`
}
// CORS defines the available cors configuration.
+3 -26
View File
@@ -2,9 +2,9 @@ package parser
import (
"errors"
"strings"
"github.com/owncloud/ocis/graph-explorer/pkg/config"
"github.com/owncloud/ocis/graph-explorer/pkg/config/defaults"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
@@ -17,28 +17,7 @@ func ParseConfig(cfg *config.Config) error {
return err
}
// 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{}
}
defaults.EnsureDefaults(cfg)
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
@@ -49,9 +28,7 @@ func ParseConfig(cfg *config.Config) error {
}
// sanitize config
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/")
}
defaults.Sanitize(cfg)
return nil
}
+1 -1
View File
@@ -2,5 +2,5 @@ package config
// Service defines the available service configuration.
type Service struct {
Name string
Name string `ocisConfig:"-" yaml:"-"`
}
+2 -2
View File
@@ -4,11 +4,11 @@ import (
"os"
"github.com/owncloud/ocis/graph/pkg/command"
"github.com/owncloud/ocis/graph/pkg/config"
"github.com/owncloud/ocis/graph/pkg/config/defaults"
)
func main() {
if err := command.Execute(config.DefaultConfig()); err != nil {
if err := command.Execute(defaults.DefaultConfig()); err != nil {
os.Exit(1)
}
}
+3 -3
View File
@@ -8,9 +8,9 @@ import (
// Config combines all available configuration parts.
type Config struct {
*shared.Commons
*shared.Commons `ocisConfig:"-" yaml:"-"`
Service Service
Service Service `ocisConfig:"-" yaml:"-"`
Tracing *Tracing `ocisConfig:"tracing"`
Log *Log `ocisConfig:"log"`
@@ -24,7 +24,7 @@ type Config struct {
Spaces Spaces `ocisConfig:"spaces"`
Identity Identity `ocisConfig:"identity"`
Context context.Context
Context context.Context `ocisConfig:"-" yaml:"-"`
}
type Spaces struct {
-55
View File
@@ -1,55 +0,0 @@
package config
func DefaultConfig() *Config {
return &Config{
Debug: Debug{
Addr: "127.0.0.1:9124",
Token: "",
},
HTTP: HTTP{
Addr: "127.0.0.1:9120",
Namespace: "com.owncloud.graph",
Root: "/graph",
},
Service: Service{
Name: "graph",
},
Reva: Reva{
Address: "127.0.0.1:9142",
},
TokenManager: TokenManager{
JWTSecret: "Pive-Fumkiu4",
},
Spaces: Spaces{
WebDavBase: "https://localhost:9200",
WebDavPath: "/dav/spaces/",
DefaultQuota: "1000000000",
Insecure: false,
},
Identity: Identity{
Backend: "cs3",
LDAP: LDAP{
URI: "ldap://localhost:9125",
Insecure: false,
BindDN: "",
BindPassword: "",
UseServerUUID: false,
WriteEnabled: false,
UserBaseDN: "ou=users,dc=ocis,dc=test",
UserSearchScope: "sub",
UserFilter: "(objectClass=inetOrgPerson)",
UserEmailAttribute: "mail",
UserDisplayNameAttribute: "displayName",
UserNameAttribute: "uid",
// FIXME: switch this to some more widely available attribute by default
// ideally this needs to be constant for the lifetime of a users
UserIDAttribute: "owncloudUUID",
GroupBaseDN: "ou=groups,dc=ocis,dc=test",
GroupSearchScope: "sub",
GroupFilter: "(objectclass=groupOfNames)",
GroupNameAttribute: "cn",
GroupIDAttribute: "owncloudUUID",
},
},
}
}
@@ -0,0 +1,93 @@
package defaults
import (
"strings"
"github.com/owncloud/ocis/graph/pkg/config"
)
func DefaultConfig() *config.Config {
return &config.Config{
Debug: config.Debug{
Addr: "127.0.0.1:9124",
Token: "",
},
HTTP: config.HTTP{
Addr: "127.0.0.1:9120",
Namespace: "com.owncloud.graph",
Root: "/graph",
},
Service: config.Service{
Name: "graph",
},
Reva: config.Reva{
Address: "127.0.0.1:9142",
},
TokenManager: config.TokenManager{
JWTSecret: "Pive-Fumkiu4",
},
Spaces: config.Spaces{
WebDavBase: "https://localhost:9200",
WebDavPath: "/dav/spaces/",
DefaultQuota: "1000000000",
Insecure: false,
},
Identity: config.Identity{
Backend: "cs3",
LDAP: config.LDAP{
URI: "ldap://localhost:9125",
Insecure: false,
BindDN: "",
BindPassword: "",
UseServerUUID: false,
WriteEnabled: false,
UserBaseDN: "ou=users,dc=ocis,dc=test",
UserSearchScope: "sub",
UserFilter: "(objectClass=inetOrgPerson)",
UserEmailAttribute: "mail",
UserDisplayNameAttribute: "displayName",
UserNameAttribute: "uid",
// FIXME: switch this to some more widely available attribute by default
// ideally this needs to be constant for the lifetime of a users
UserIDAttribute: "owncloudUUID",
GroupBaseDN: "ou=groups,dc=ocis,dc=test",
GroupSearchScope: "sub",
GroupFilter: "(objectclass=groupOfNames)",
GroupNameAttribute: "cn",
GroupIDAttribute: "owncloudUUID",
},
},
}
}
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{}
}
}
func Sanitize(cfg *config.Config) {
// sanitize config
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/")
}
}
+1 -1
View File
@@ -3,6 +3,6 @@ package config
// HTTP defines the available http configuration.
type HTTP struct {
Addr string `ocisConfig:"addr" env:"GRAPH_HTTP_ADDR"`
Namespace string
Namespace string `ocisConfig:"-" yaml:"-"`
Root string `ocisConfig:"root" env:"GRAPH_HTTP_ROOT"`
}
+3 -27
View File
@@ -2,9 +2,9 @@ package parser
import (
"errors"
"strings"
"github.com/owncloud/ocis/graph/pkg/config"
"github.com/owncloud/ocis/graph/pkg/config/defaults"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
@@ -17,28 +17,7 @@ func ParseConfig(cfg *config.Config) error {
return err
}
// 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{}
}
defaults.EnsureDefaults(cfg)
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
@@ -48,10 +27,7 @@ func ParseConfig(cfg *config.Config) error {
}
}
// sanitize config
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/")
}
defaults.Sanitize(cfg)
return nil
}
+1 -1
View File
@@ -2,5 +2,5 @@ package config
// Service defines the available service configuration.
type Service struct {
Name string
Name string `ocisConfig:"-" yaml:"-"`
}
+2 -2
View File
@@ -15,7 +15,7 @@ import (
. "github.com/onsi/gomega"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/graph/mocks"
"github.com/owncloud/ocis/graph/pkg/config"
"github.com/owncloud/ocis/graph/pkg/config/defaults"
service "github.com/owncloud/ocis/graph/pkg/service/v0"
"github.com/owncloud/ocis/graph/pkg/service/v0/errorcode"
"github.com/stretchr/testify/mock"
@@ -34,7 +34,7 @@ var _ = Describe("Graph", func() {
gatewayClient = &mocks.GatewayClient{}
httpClient = &mocks.HTTPClient{}
svc = service.NewService(
service.Config(config.DefaultConfig()),
service.Config(defaults.DefaultConfig()),
service.WithGatewayClient(gatewayClient),
service.WithHTTPClient(httpClient),
)
+2 -2
View File
@@ -4,11 +4,11 @@ import (
"os"
"github.com/owncloud/ocis/idm/pkg/command"
"github.com/owncloud/ocis/idm/pkg/config"
"github.com/owncloud/ocis/idm/pkg/config/defaults"
)
func main() {
if err := command.Execute(config.DefaultConfig()); err != nil {
if err := command.Execute(defaults.DefaultConfig()); err != nil {
os.Exit(1)
}
}
+11
View File
@@ -0,0 +1,11 @@
package idm
import (
_ "embed"
)
//go:embed ldif/base.ldif.tmpl
var BaseLDIF string
//go:embed ldif/demousers.ldif
var DemoUsersLDIF string
+24
View File
@@ -0,0 +1,24 @@
dn: o=libregraph-idm
o: libregraph-idm
objectClass: organization
dn: ou=users,o=libregraph-idm
objectClass: organizationalUnit
ou: users
dn: ou=sysusers,o=libregraph-idm
objectClass: organizationalUnit
ou: users
dn: ou=groups,o=libregraph-idm
objectClass: organizationalUnit
ou: groups
{{ range . -}}
dn: uid={{ .Name }},ou=sysusers,o=libregraph-idm
objectClass: account
objectClass: simpleSecurityObject
uid: {{ .Name }}
userPassword:: {{ .Password }}
{{ end -}}
+162
View File
@@ -0,0 +1,162 @@
dn: uid=einstein,ou=users,o=libregraph-idm
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: ownCloud
objectClass: person
objectClass: top
uid: einstein
givenName: Albert
sn: Einstein
cn: einstein
displayName: Albert Einstein
description: A German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics).
mail: einstein@example.org
ownCloudUUID: 4c510ada-c86b-4815-8820-42cdf82c3d51
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTY1NTM2LHQ9MSxwPTIkOFpyclR0NXA1a0VmVlhL
akNHaVBEUSRnemZCWWwrTHdzTUhXQWJSMEJ2NnRiZk1XZjZaOVJ0Mms5Z3VkSWJ5bzg4
dn: uid=marie,ou=users,o=libregraph-idm
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: ownCloud
objectClass: person
objectClass: top
uid: marie
givenName: Marie
sn: Curie
cn: marie
displayName: Marie Skłodowska Curie
description: A Polish and naturalized-French physicist and chemist who conducted pioneering research on radioactivity.
mail: marie@example.org
ownCloudUUID: f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTY1NTM2LHQ9MSxwPTIkUHJzWkpQQW9pMkFwZHlJ
a2Q1NGkzQSRnalZzR3doTmk2K0djenJ4SVdPalN2UlBpWXhKSXpHVG4vcnpQZzkvSlZN
dn: uid=richard,ou=users,o=libregraph-idm
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: ownCloud
objectClass: person
objectClass: top
uid: richard
givenName: Richard
sn: Feynman
cn: richard
displayName: Richard Phillips Feynman
description: An American theoretical physicist, known for his work in the path integral formulation of quantum mechanics, the theory of quantum electrodynamics, the physics of the superfluidity of supercooled liquid helium, as well as his work in particle physics for which he proposed the parton model.
mail: richard@example.org
ownCloudUUID: 932b4540-8d16-481e-8ef4-588e4b6b151c
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTY1NTM2LHQ9MSxwPTIkNjlNcUQxem5sUUZ2SUha
d2dxU00xQSRVQmNEa2NDZktMemVpQnlyb0JjOTdCSVRhTFo2WjZIL2dhbytSTVh6OHhn
dn: uid=moss,ou=users,o=libregraph-idm
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: ownCloud
objectClass: person
objectClass: top
uid: moss
givenName: Maurice
sn: Moss
cn: moss
displayName: Maurice Moss
description: A worker in the IT Department of Reynholm Industries. Of all the working staff in the IT Department, he is the most hard-working, the most experienced, and the most capable of doing his job well. He puts a lot of effort into his work, however he does not get the credit he deserves.
mail: moss@example.org
ownCloudUUID: 058bff95-6708-4fe5-91e4-9ea3d377588b
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTY1NTM2LHQ9MSxwPTIkZU0xaXR6amQ2dlNSSERx
NlZCbXBlQSQxNzBhcTB3YjJZZ2NLU2cwWDhHY3l6ckZwMUllcGplMTNraDdVNjUyNXk4
dn: uid=admin,ou=users,o=libregraph-idm
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: ownCloud
objectClass: person
objectClass: top
uid: admin
givenName: Admin
sn: Admin
cn: admin
displayName: Admin
description: An admin for this oCIS instance.
mail: admin@example.org
ownCloudUUID: ddc2004c-0977-11eb-9d3f-a793888cd0f8
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTY1NTM2LHQ9MSxwPTIkRXdwYUhJeVErcG9wdkcv
Tk81R0o2USRNWHp4czNvdHBhOWp3S0hxc1lLMlZodzAralUxSFowMUNpOXducWZlT1pn
dn: cn=users,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: users
description: Users
ownCloudUUID: 509a9dcd-bb37-4f4f-a01a-19dca27d9cfa
member: uid=einstein,ou=users,o=libregraph-idm
member: uid=marie,ou=users,o=libregraph-idm
member: uid=richard,ou=users,o=libregraph-idm
member: uid=moss,ou=users,o=libregraph-idm
member: uid=admin,ou=users,o=libregraph-idm
dn: cn=sailing-lovers,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: sailing-lovers
description: Sailing lovers
ownCloudUUID: 6040aa17-9c64-4fef-9bd0-77234d71bad0
member: uid=einstein,ou=users,o=libregraph-idm
dn: cn=violin-haters,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: violin-haters
description: Violin haters
ownCloudUUID: dd58e5ec-842e-498b-8800-61f2ec6f911f
member: uid=einstein,ou=users,o=libregraph-idm
dn: cn=radium-lovers,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: radium-lovers
description: Radium lovers
ownCloudUUID: 7b87fd49-286e-4a5f-bafd-c535d5dd997a
member: uid=marie,ou=users,o=libregraph-idm
dn: cn=polonium-lovers,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: polonium-lovers
description: Polonium lovers
ownCloudUUID: cedc21aa-4072-4614-8676-fa9165f598ff
member: uid=marie,ou=users,o=libregraph-idm
dn: cn=quantum-lovers,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: quantum-lovers
description: Quantum lovers
ownCloudUUID: a1726108-01f8-4c30-88df-2b1a9d1cba1a
member: uid=richard,ou=users,o=libregraph-idm
dn: cn=philosophy-haters,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: philosophy-haters
description: Philosophy haters
ownCloudUUID: 167cbee2-0518-455a-bfb2-031fe0621e5d
member: uid=richard,ou=users,o=libregraph-idm
dn: cn=physics-lovers,ou=groups,o=libregraph-idm
objectClass: groupOfNames
objectClass: ownCloud
objectClass: top
cn: physics-lovers
description: Physics lovers
ownCloudUUID: 262982c1-2362-4afa-bfdf-8cbfef64a06e
member: uid=einstein,ou=users,o=libregraph-idm
member: uid=marie,ou=users,o=libregraph-idm
member: uid=richard,ou=users,o=libregraph-idm
+45 -34
View File
@@ -13,6 +13,7 @@ import (
"github.com/libregraph/idm/pkg/ldappassword"
"github.com/libregraph/idm/pkg/ldbbolt"
"github.com/libregraph/idm/server"
"github.com/owncloud/ocis/idm"
"github.com/owncloud/ocis/idm/pkg/config"
"github.com/owncloud/ocis/idm/pkg/config/parser"
"github.com/owncloud/ocis/idm/pkg/logging"
@@ -53,7 +54,7 @@ func start(ctx context.Context, logger log.Logger, cfg *config.Config) error {
TLSCertFile: cfg.IDM.Cert,
TLSKeyFile: cfg.IDM.Key,
LDAPBaseDN: "o=libregraph-idm",
LDAPAdminDN: "uid=libregrah,o=libregraph-idm",
LDAPAdminDN: "uid=libregraph,ou=sysusers,o=libregraph-idm",
BoltDBFile: cfg.IDM.DatabasePath,
}
@@ -80,15 +81,26 @@ func start(ctx context.Context, logger log.Logger, cfg *config.Config) error {
func bootstrap(logger log.Logger, cfg *config.Config, srvcfg server.Config) error {
// Hash password if the config does not supply a hash already
var pwhash string
var err error
if strings.HasPrefix(cfg.IDM.AdminPassword, "$argon2id$") {
// password is alread hashed
pwhash = "{ARGON2}" + cfg.IDM.AdminPassword
} else {
if pwhash, err = ldappassword.Hash(cfg.IDM.AdminPassword, "{ARGON2}"); err != nil {
return err
}
type svcUser struct {
Name string
Password string
}
serviceUsers := []svcUser{
{
Name: "libregraph",
Password: cfg.ServiceUserPasswords.IdmAdmin,
},
{
Name: "idp",
Password: cfg.ServiceUserPasswords.Idp,
},
{
Name: "reva",
Password: cfg.ServiceUserPasswords.Reva,
},
}
bdb := &ldbbolt.LdbBolt{}
@@ -103,22 +115,38 @@ func bootstrap(logger log.Logger, cfg *config.Config, srvcfg server.Config) erro
}
// Prepare the initial Data from template. To be able to set the
// supplied admin password
tmpl, err := template.New("baseldif").Parse(baseldif)
// supplied service user passwords
tmpl, err := template.New("baseldif").Parse(idm.BaseLDIF)
if err != nil {
return err
}
for i := range serviceUsers {
if strings.HasPrefix(serviceUsers[i].Password, "$argon2id$") {
// password is alread hashed
serviceUsers[i].Password = "{ARGON2}" + serviceUsers[i].Password
} else {
if serviceUsers[i].Password, err = ldappassword.Hash(serviceUsers[i].Password, "{ARGON2}"); err != nil {
return err
}
}
// We need to treat the hash as binary in the LDIF template to avoid
// go-ldap/ldif to to any fancy escaping
serviceUsers[i].Password = base64.StdEncoding.EncodeToString([]byte(serviceUsers[i].Password))
}
var tmplWriter strings.Builder
// We need to treat the hash as binary in the LDIF template to avoid
// go-ldap/ldif to to any fancy escaping
b64 := base64.StdEncoding.EncodeToString([]byte(pwhash))
err = tmpl.Execute(&tmplWriter, b64)
err = tmpl.Execute(&tmplWriter, serviceUsers)
if err != nil {
return err
}
s := strings.NewReader(tmplWriter.String())
bootstrapData := tmplWriter.String()
if cfg.CreateDemoUsers {
bootstrapData = bootstrapData + "\n" + idm.DemoUsersLDIF
}
s := strings.NewReader(bootstrapData)
lf := &ldif.LDIF{}
err = ldif.Unmarshal(s, lf)
if err != nil {
@@ -131,23 +159,6 @@ func bootstrap(logger log.Logger, cfg *config.Config, srvcfg server.Config) erro
return fmt.Errorf("error adding Entry '%s': %w", entry.DN, err)
}
}
return nil
}
var baseldif string = `dn: o=libregraph-idm
o: libregraph-idm
objectClass: organization
dn: ou=users,o=libregraph-idm
objectClass: organizationalUnit
ou: users
dn: ou=groups,o=libregraph-idm
objectClass: organizationalUnit
ou: groups
dn: uid=libregraph,o=libregraph-idm
objectClass: account
objectClass: simpleSecurityObject
uid: libregraph
userPassword:: {{.}}`
+17 -9
View File
@@ -8,23 +8,31 @@ import (
// Config combines all available configuration parts.
type Config struct {
*shared.Commons
*shared.Commons `ocisConfig:"-" yaml:"-"`
Service Service
Service Service `ocisConfig:"-" yaml:"-"`
Tracing *Tracing `ocisConfig:"tracing"`
Log *Log `ocisConfig:"log"`
Debug Debug `ocisConfig:"debug"`
IDM Settings `ocisConfig:"idm"`
IDM Settings `ocisConfig:"idm"`
CreateDemoUsers bool `ocisConfig:"create_demo_users" env:"IDM_CREATE_DEMO_USERS;ACCOUNTS_DEMO_USERS_AND_GROUPS" desc:"Flag to enabe/disable the creation of the demo users"`
Context context.Context
ServiceUserPasswords ServiceUserPasswords `ocisConfig:"service_user_passwords"`
Context context.Context `ocisConfig:"-" yaml:"-"`
}
type Settings struct {
LDAPSAddr string `ocisConfig:"ldaps_addr" env:"IDM_LDAPS_ADDR"`
Cert string `ocisConfig:"cert" env:"IDM_LDAPS_CERT"`
Key string `ocisConfig:"cert" env:"IDM_LDAPS_KEY"`
DatabasePath string `ocisConfig:"database" env:"IDM_DATABASE_PATH"`
AdminPassword string `ocisConfig:"admin_password" env:"IDM_ADMIN_PASSWORD"`
LDAPSAddr string `ocisConfig:"ldaps_addr" env:"IDM_LDAPS_ADDR" desc:"Listen address for the ldaps listener (ip-addr:port)"`
Cert string `ocisConfig:"cert" env:"IDM_LDAPS_CERT" desc:"File name of the TLS server certificate for the ldaps listener"`
Key string `ocisConfig:"cert" env:"IDM_LDAPS_KEY" desc:"File name for the TLS certificate key for the server certificate"`
DatabasePath string `ocisConfig:"database" env:"IDM_DATABASE_PATH" desc:"Full path to the idm backend database"`
}
type ServiceUserPasswords struct {
IdmAdmin string `ocisConfig:"admin_password" env:"IDM_ADMIN_PASSWORD" desc:"Password to set for the \"idm\" service users. Either cleartext or an argon2id hash"`
Reva string `ocisConfig:"reva_password" env:"IDM_REVASVC_PASSWORD" desc:"Password to set for the \"reva\" service users. Either cleartext or an argon2id hash"`
Idp string `ocisConfig:"idp_password" env:"IDM_IDPSVC_PASSWORD" desc:"Password to set for the \"idp\" service users. Either cleartext or an argon2id hash"`
}
+10 -5
View File
@@ -11,12 +11,17 @@ func DefaultConfig() *Config {
Service: Service{
Name: "idm",
},
CreateDemoUsers: true,
ServiceUserPasswords: ServiceUserPasswords{
IdmAdmin: "idm",
Idp: "idp",
Reva: "reva",
},
IDM: Settings{
LDAPSAddr: "127.0.0.1:9235",
Cert: path.Join(defaults.BaseDataPath(), "idm", "ldap.crt"),
Key: path.Join(defaults.BaseDataPath(), "idm", "ldap.key"),
DatabasePath: path.Join(defaults.BaseDataPath(), "idm", "ocis.boltdb"),
AdminPassword: "admin",
LDAPSAddr: "127.0.0.1:9235",
Cert: path.Join(defaults.BaseDataPath(), "idm", "ldap.crt"),
Key: path.Join(defaults.BaseDataPath(), "idm", "ldap.key"),
DatabasePath: path.Join(defaults.BaseDataPath(), "idm", "ocis.boltdb"),
},
}
}
+60
View File
@@ -0,0 +1,60 @@
package defaults
import (
"path"
"github.com/owncloud/ocis/idm/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)
func FullDefaultConfig() *config.Config {
cfg := DefaultConfig()
EnsureDefaults(cfg)
Sanitize(cfg)
return cfg
}
func DefaultConfig() *config.Config {
return &config.Config{
Service: config.Service{
Name: "idm",
},
IDM: config.Settings{
LDAPSAddr: "127.0.0.1:9235",
Cert: path.Join(defaults.BaseDataPath(), "idm", "ldap.crt"),
Key: path.Join(defaults.BaseDataPath(), "idm", "ldap.key"),
DatabasePath: path.Join(defaults.BaseDataPath(), "idm", "ocis.boltdb"),
},
}
}
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{}
}
}
func Sanitize(cfg *config.Config) {
// nothing to sanitize here
}
+4 -23
View File
@@ -4,6 +4,7 @@ import (
"errors"
"github.com/owncloud/ocis/idm/pkg/config"
"github.com/owncloud/ocis/idm/pkg/config/defaults"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
@@ -16,29 +17,7 @@ func ParseConfig(cfg *config.Config) error {
return err
}
// 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{}
}
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"
@@ -47,5 +26,7 @@ func ParseConfig(cfg *config.Config) error {
}
}
defaults.Sanitize(cfg)
return nil
}
+1 -1
View File
@@ -2,5 +2,5 @@ package config
// Service defines the available service configuration.
type Service struct {
Name string
Name string `ocisConfig:"-" yaml:"-"`
}

Some files were not shown because too many files have changed in this diff Show More