mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-06 11:31:00 -05:00
Merge branch 'master' into StoreSettingsViaMetadata
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
+9
-3
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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:"-"`
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}},
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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",
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
// Service defines the available service configuration.
|
||||
type Service struct {
|
||||
Name string `ocisConfig:"-" yaml:"-"`
|
||||
}
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 ""
|
||||
}
|
||||
}
|
||||
@@ -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{},
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 +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" >}}
|
||||
@@ -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 >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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 |
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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" >}}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 >}}
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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" >}}).
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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:"-"`
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ package config
|
||||
|
||||
// Service defines the available service configuration.
|
||||
type Service struct {
|
||||
Name string
|
||||
Name string `ocisConfig:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ package config
|
||||
|
||||
// Service defines the available service configuration.
|
||||
type Service struct {
|
||||
Name string
|
||||
Name string `ocisConfig:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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, "/")
|
||||
}
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ package config
|
||||
|
||||
// Service defines the available service configuration.
|
||||
type Service struct {
|
||||
Name string
|
||||
Name string `ocisConfig:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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 -}}
|
||||
@@ -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
@@ -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:: {{.}}`
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user