diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index c3a6f1db5b..cd90d103da 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -1,4 +1,4 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.5.2. DO NOT EDIT. +# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.6. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. BINGO_DIR := $(dir $(lastword $(MAKEFILE_LIST))) GOPATH ?= $(shell go env GOPATH) diff --git a/.bingo/variables.env b/.bingo/variables.env index e19cf5f1db..d64a412b02 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -1,4 +1,4 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.5.2. DO NOT EDIT. +# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.6. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. # Those variables will work only until 'bingo get' was invoked, or if tools were installed via Makefile's Variables.mk. GOBIN=${GOBIN:=$(go env GOBIN)} diff --git a/.drone.env b/.drone.env index 80928acefd..6b702be1e1 100644 --- a/.drone.env +++ b/.drone.env @@ -1,5 +1,5 @@ # The test runner source for API tests -CORE_COMMITID=8f4783aa71a2fd6e863b2a4534fc697d5455bc45 +CORE_COMMITID=f73c5f6086921d858d19c1013f1cbf762c8e27dd CORE_BRANCH=master # The test runner source for UI tests diff --git a/.drone.star b/.drone.star index ff5aad4eaa..54021c12d7 100644 --- a/.drone.star +++ b/.drone.star @@ -18,7 +18,7 @@ OC_CI_NODEJS = "owncloudci/nodejs:%s" OC_CI_PHP = "owncloudci/php:%s" OC_CI_WAIT_FOR = "owncloudci/wait-for:latest" OC_CS3_API_VALIDATOR = "owncloud/cs3api-validator:latest" -OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.5.0" +OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.6.0" OC_SERVER = "owncloud/server:10" OC_UBUNTU = "owncloud/ubuntu:18.04" OSIXIA_OPEN_LDAP = "osixia/openldap:latest" @@ -698,7 +698,7 @@ def uiTestPipeline(ctx, filterTags, early_fail, runPart = 1, numberOfParts = 1, "arch": "amd64", }, "steps": skipIfUnchanged(ctx, "acceptance-tests") + restoreBuildArtifactCache(ctx, "ocis-binary-amd64", "ocis/bin/ocis") + - ocisServerWithAccounts(storage, accounts_hash_difficulty, [stepVolumeOC10Tests]) + waitForSeleniumService() + waitForMiddlewareService() + [ + ocisServer(storage, accounts_hash_difficulty, [stepVolumeOC10Tests]) + waitForSeleniumService() + waitForMiddlewareService() + [ { "name": "webUITests", "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION, @@ -1654,7 +1654,7 @@ def ocisServerWithAccounts(storage, accounts_hash_difficulty = 4, volumes = [], "IDP_LDAP_LOGIN_ATTRIBUTE": "uid", "PROXY_ACCOUNT_BACKEND_TYPE": "accounts", "OCS_ACCOUNT_BACKEND_TYPE": "accounts", - "OCIS_RUN_EXTENSIONS": "settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,proxy,idp,nats,accounts,glauth,ocdav", + "OCIS_RUN_EXTENSIONS": "settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,frontend,gateway,user,group,auth-basic,auth-bearer,auth-machine,storage-users,storage-shares,storage-publiclink,appprovider,sharing,proxy,idp,nats,accounts,glauth,ocdav", "OCIS_INSECURE": "true", "PROXY_ENABLE_BASIC_AUTH": "true", "IDP_INSECURE": "true", @@ -1680,6 +1680,7 @@ def ocisServerWithAccounts(storage, accounts_hash_difficulty = 4, volumes = [], "detach": True, "environment": environment, "commands": [ + "ocis/bin/ocis init --insecure true", "ocis/bin/ocis server", ], "volumes": volumes, @@ -1700,8 +1701,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = user = "0:0" environment = { "OCIS_URL": "https://ocis-server:9200", - "GATEWAY_GRPC_ADDR": "0.0.0.0:9142", - "STORAGE_HOME_DRIVER": "%s" % (storage), + "GATEWAY_GRPC_ADDR": "0.0.0.0:9142", # cs3api-validator needs the cs3api gatway exposed "STORAGE_USERS_DRIVER": "%s" % (storage), "STORAGE_USERS_DRIVER_LOCAL_ROOT": "/srv/app/tmp/ocis/local/root", "STORAGE_USERS_DRIVER_OCIS_ROOT": "/srv/app/tmp/ocis/storage/users", @@ -1712,8 +1712,8 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = "IDP_IDENTIFIER_REGISTRATION_CONF": "/drone/src/tests/config/drone/identifier-registration.yml", "OCIS_LOG_LEVEL": "error", "SETTINGS_DATA_PATH": "/srv/app/tmp/ocis/settings", - "OCIS_INSECURE": "true", "IDM_CREATE_DEMO_USERS": True, + "IDM_ADMIN_PASSWORD": "admin", # override the random admin password from `ocis init` } wait_for_ocis = { "name": "wait-for-ocis-server", @@ -1782,24 +1782,16 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = "SHARING_USER_SQL_HOST": "oc10-db", "SHARING_USER_SQL_PORT": 3306, "SHARING_USER_SQL_NAME": "owncloud", - # ownCloud storage readonly - # TODO: conflict with OWNCLOUDSQL -> https://github.com/owncloud/ocis/issues/2303 - "OCIS_STORAGE_READ_ONLY": "false", # General oCIS config # OCIS_RUN_EXTENSIONS specifies to start all extensions except glauth, idp and accounts. These are replaced by external services - "OCIS_RUN_EXTENSIONS": "settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,proxy,nats,ocdav", + "OCIS_RUN_EXTENSIONS": "settings,storage-metadata,graph,graph-explorer,ocs,store,thumbnails,web,webdav,frontend,gateway,user,group,auth-basic,auth-bearer,auth-machine,storage-users,storage-shares,storage-publiclink,appprovider,sharing,proxy,nats,ocdav", "OCIS_LOG_LEVEL": "info", "OCIS_URL": OCIS_URL, - "PROXY_TLS": "true", "OCIS_BASE_DATA_PATH": "/mnt/data/ocis", "OCIS_CONFIG_DIR": "/etc/ocis", - # change default secrets - "OCIS_JWT_SECRET": "Pive-Fumkiu4", - "STORAGE_TRANSFER_SECRET": "replace-me-with-a-transfer-secret", - "OCIS_MACHINE_AUTH_API_KEY": "change-me-please", - "OCIS_INSECURE": "true", "PROXY_ENABLE_BASIC_AUTH": "true", "IDM_CREATE_DEMO_USERS": True, + "IDM_ADMIN_PASSWORD": "admin", # override the random admin password from `ocis init` } wait_for_ocis = { "name": "wait-for-ocis-server", @@ -1825,6 +1817,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = "environment": environment, "user": user, "commands": [ + "ocis/bin/ocis init --insecure true", "ocis/bin/ocis server", ], "volumes": volumes, @@ -1845,6 +1838,7 @@ def middlewareService(): "REMOTE_UPLOAD_DIR": "/uploads", "NODE_TLS_REJECT_UNAUTHORIZED": "0", "MIDDLEWARE_HOST": "middleware", + "TEST_WITH_GRAPH_API": "true", }, "volumes": [{ "name": "uploads", diff --git a/.vscode/launch.json b/.vscode/launch.json index 4332cf2e1a..aec90a875e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,9 +19,25 @@ "PROXY_ENABLE_BASIC_AUTH": "true", // set insecure options because we don't have valid certificates in dev environments "OCIS_INSECURE": "true", + // set some hardcoded secrets + "OCIS_JWT_SECRET": "some-ocis-jwt-secret", + "STORAGE_TRANSFER_SECRET": "some-ocis-transfer-secret", + "OCIS_MACHINE_AUTH_API_KEY": "some-ocis-machine-auth-api-key", + // idm ldap + "IDM_SVC_PASSWORD": "some-ldap-idm-password", + "GRAPH_LDAP_BIND_PASSWORD": "some-ldap-idm-password", + // reva ldap + "IDM_REVASVC_PASSWORD": "some-ldap-reva-password", + "GROUPS_LDAP_BIND_PASSWORD": "some-ldap-reva-password", + "USERS_LDAP_BIND_PASSWORD": "some-ldap-reva-password", + "AUTH_BASIC_LDAP_BIND_PASSWORD": "some-ldap-reva-password", + // idp ldap + "IDM_IDPSVC_PASSWORD": "some-ldap-idp-password", + "IDP_LDAP_BIND_PASSWORD": "some-ldap-idp-password", + // admin user default password + "IDM_ADMIN_PASSWORD": "admin", // demo users - "ACCOUNTS_DEMO_USERS_AND_GROUPS": "true", - "IDM_CREATE_DEMO_USERS": "true" + "IDM_CREATE_DEMO_USERS": "true", // OCIS_RUN_EXTENSIONS allows to start a subset of extensions even in the supervised mode //"OCIS_RUN_EXTENSIONS": "settings,storage-metadata,glauth,graph,graph-explorer,idp,ocs,store,thumbnails,web,webdav,storage-frontend,storage-gateway,storage-userprovider,storage-groupprovider,storage-authbasic,storage-authbearer,storage-authmachine,storage-users,storage-shares,storage-public-link,storage-appprovider,storage-sharing,accounts,proxy,ocdav", } diff --git a/CHANGELOG.md b/CHANGELOG.md index 897fc4f668..400ef744bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,13 @@ The following sections list the changes for unreleased. * Bugfix - Return proper errors when ocs/cloud/users is using the cs3 backend: [#3483](https://github.com/owncloud/ocis/issues/3483) * Bugfix - URL encode the webdav url in the graph API: [#3597](https://github.com/owncloud/ocis/pull/3597) * Change - Load configuration files just from one directory: [#3587](https://github.com/owncloud/ocis/pull/3587) +* Change - Introduce `ocis init` and remove all default secrets: [#3551](https://github.com/owncloud/ocis/pull/3551) +* Change - Reduce drives in graph /me/drives API: [#3629](https://github.com/owncloud/ocis/pull/3629) * Change - Switched default configuration to use libregraph/idm: [#3331](https://github.com/owncloud/ocis/pull/3331) +* Enhancement - Align service naming: [#3606](https://github.com/owncloud/ocis/pull/3606) +* Enhancement - Wrap metadata storage with dedicated reva gateway: [#3602](https://github.com/owncloud/ocis/pull/3602) * Enhancement - Add capability for public link single file edit: [#6787](https://github.com/owncloud/web/pull/6787) +* Enhancement - Added `share_jail` and `projects` feature flags in spaces capability: [#3626](https://github.com/owncloud/ocis/pull/3626) * Enhancement - Update linkshare capabilities: [#3579](https://github.com/owncloud/ocis/pull/3579) * Enhancement - Update reva to v2.x.x: [#3552](https://github.com/owncloud/ocis/pull/3552) @@ -52,6 +57,24 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/3587 +* Change - Introduce `ocis init` and remove all default secrets: [#3551](https://github.com/owncloud/ocis/pull/3551) + + We've removed all default secrets. This means you can't start oCIS any longer without setting + these via environment variable or configuration file. + + In order to make this easy for you, we introduced a new command: `ocis init`. You can run this + command before starting oCIS with `ocis server` and it will bootstrap you a configuration file + for a secure oCIS instance. + + https://github.com/owncloud/ocis/pull/3551 + +* Change - Reduce drives in graph /me/drives API: [#3629](https://github.com/owncloud/ocis/pull/3629) + + Reduced the drives in the graph `/me/drives` API to only the drives the user has access to. The + endpoint `/drives` will list all drives when the user has the permission. + + https://github.com/owncloud/ocis/pull/3629 + * Change - Switched default configuration to use libregraph/idm: [#3331](https://github.com/owncloud/ocis/pull/3331) We switched the default configuration of oCIS to use the "idm" service (based on @@ -61,6 +84,22 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/3331 https://github.com/owncloud/ocis/pull/3633 +* Enhancement - Align service naming: [#3606](https://github.com/owncloud/ocis/pull/3606) + + We now reflect the configured service names when listing them in the ocis runtime + + https://github.com/owncloud/ocis/issues/3603 + https://github.com/owncloud/ocis/pull/3606 + +* Enhancement - Wrap metadata storage with dedicated reva gateway: [#3602](https://github.com/owncloud/ocis/pull/3602) + + We wrapped the metadata storage in a minimal reva instance with a dedicated gateway, including + static storage registry, static auth registry, in memory userprovider, machine + authprovider and demo permissions service. This allows us to preconfigure the service user + for the ocis settings service, share and public share providers. + + https://github.com/owncloud/ocis/pull/3602 + * Enhancement - Add capability for public link single file edit: [#6787](https://github.com/owncloud/web/pull/6787) It is now possible to share a single file by link with edit permissions. Therefore we need a @@ -70,6 +109,13 @@ The following sections list the changes for unreleased. https://github.com/owncloud/web/pull/6787 https://github.com/owncloud/ocis/pull/3538 +* Enhancement - Added `share_jail` and `projects` feature flags in spaces capability: [#3626](https://github.com/owncloud/ocis/pull/3626) + + We've added feature flags to the `spaces` capability to indicate to clients which features are + supposed to be shown to users. + + https://github.com/owncloud/ocis/pull/3626 + * Enhancement - Update linkshare capabilities: [#3579](https://github.com/owncloud/ocis/pull/3579) We have updated the capabilities regarding password enforcement and expiration dates of @@ -84,11 +130,14 @@ The following sections list the changes for unreleased. * TODO + https://github.com/owncloud/ocis/issues/3621 https://github.com/owncloud/ocis/pull/3552 https://github.com/owncloud/ocis/pull/3570 https://github.com/owncloud/ocis/pull/3601 + https://github.com/owncloud/ocis/pull/3602 https://github.com/owncloud/ocis/pull/3605 https://github.com/owncloud/ocis/pull/3611 + https://github.com/owncloud/ocis/pull/3637 # Changelog for [1.20.0] (2022-04-13) The following sections list the changes for 1.20.0. diff --git a/changelog/unreleased/align-service-naming.md b/changelog/unreleased/align-service-naming.md new file mode 100644 index 0000000000..dfcff86e86 --- /dev/null +++ b/changelog/unreleased/align-service-naming.md @@ -0,0 +1,6 @@ +Enhancement: align service naming + +We now reflect the configured service names when listing them in the ocis runtime + +https://github.com/owncloud/ocis/pull/3606 +https://github.com/owncloud/ocis/issues/3603 \ No newline at end of file diff --git a/changelog/unreleased/change-ocis-init.md b/changelog/unreleased/change-ocis-init.md new file mode 100644 index 0000000000..a4a81eb385 --- /dev/null +++ b/changelog/unreleased/change-ocis-init.md @@ -0,0 +1,10 @@ +Change: Introduce `ocis init` and remove all default secrets + +We've removed all default secrets. This means you can't start oCIS any longer +without setting these via environment variable or configuration file. + +In order to make this easy for you, we introduced a new command: `ocis init`. +You can run this command before starting oCIS with `ocis server` and it will +bootstrap you a configuration file for a secure oCIS instance. + +https://github.com/owncloud/ocis/pull/3551 diff --git a/changelog/unreleased/graph-me-drives.md b/changelog/unreleased/graph-me-drives.md new file mode 100644 index 0000000000..3104450cd9 --- /dev/null +++ b/changelog/unreleased/graph-me-drives.md @@ -0,0 +1,6 @@ +Change: Reduce drives in graph /me/drives API + +Reduced the drives in the graph `/me/drives` API to only the drives the user has access to. +The endpoint `/drives` will list all drives when the user has the permission. + +https://github.com/owncloud/ocis/pull/3629 diff --git a/changelog/unreleased/metadata-gateway.md b/changelog/unreleased/metadata-gateway.md new file mode 100644 index 0000000000..3205409fb2 --- /dev/null +++ b/changelog/unreleased/metadata-gateway.md @@ -0,0 +1,5 @@ +Enhancement: wrap metadata storage with dedicated reva gateway + +We wrapped the metadata storage in a minimal reva instance with a dedicated gateway, including static storage registry, static auth registry, in memory userprovider, machine authprovider and demo permissions service. This allows us to preconfigure the service user for the ocis settings service, share and public share providers. + +https://github.com/owncloud/ocis/pull/3602 diff --git a/changelog/unreleased/spaces-capabilities.md b/changelog/unreleased/spaces-capabilities.md new file mode 100644 index 0000000000..f2a90c4076 --- /dev/null +++ b/changelog/unreleased/spaces-capabilities.md @@ -0,0 +1,5 @@ +Enhancement: Added `share_jail` and `projects` feature flags in spaces capability + +We've added feature flags to the `spaces` capability to indicate to clients which features are supposed to be shown to users. + +https://github.com/owncloud/ocis/pull/3626 diff --git a/changelog/unreleased/update-reva.md b/changelog/unreleased/update-reva.md index 0cce56ff61..e20b931707 100644 --- a/changelog/unreleased/update-reva.md +++ b/changelog/unreleased/update-reva.md @@ -7,5 +7,8 @@ Updated reva to version 2.x.x. This update includes: https://github.com/owncloud/ocis/pull/3552 https://github.com/owncloud/ocis/pull/3570 https://github.com/owncloud/ocis/pull/3601 +https://github.com/owncloud/ocis/pull/3602 https://github.com/owncloud/ocis/pull/3605 https://github.com/owncloud/ocis/pull/3611 +https://github.com/owncloud/ocis/issues/3621 +https://github.com/owncloud/ocis/pull/3637 diff --git a/deployments/examples/ocis_traefik/.env b/deployments/examples/ocis_traefik/.env index f75e2d5fb9..478247e879 100644 --- a/deployments/examples/ocis_traefik/.env +++ b/deployments/examples/ocis_traefik/.env @@ -2,10 +2,6 @@ # It skips certificate validation for various parts of oCIS and is needed if you use self signed certificates. INSECURE=true -# The demo users should not be created on a production instance -# because their passwords are public -DEMO_USERS=true - ### Traefik settings ### # Serve Traefik dashboard. Defaults to "false". TRAEFIK_DASHBOARD= @@ -21,16 +17,11 @@ TRAEFIK_ACME_MAIL= OCIS_DOCKER_TAG= # Domain of oCIS, where you can find the frontend. Defaults to "ocis.owncloud.test" OCIS_DOMAIN= -# IDP LDAP bind password. Must be changed in order to have a secure oCIS. Defaults to "idp". -IDP_LDAP_BIND_PASSWORD= -# Storage LDAP bind password. Must be changed in order to have a secure oCIS. Defaults to "reva". -STORAGE_LDAP_BIND_PASSWORD= -# JWT secret which is used for the storage provider. Must be changed in order to have a secure oCIS. Defaults to "Pive-Fumkiu4" -OCIS_JWT_SECRET= -# JWT secret which is used for uploads to create transfer tokens. Must be changed in order to have a secure oCIS. Defaults to "replace-me-with-a-transfer-secret" -STORAGE_TRANSFER_SECRET= -# Machine auth api key secret. Must be changed in order to have a secure oCIS. Defaults to "change-me-please" -OCIS_MACHINE_AUTH_API_KEY= +# oCIS admin user password. Defaults to "admin". +ADMIN_PASSWORD= +# The demo users should not be created on a production instance +# because their passwords are public. Defaults to "false". +DEMO_USERS= # If you want to use debugging and tracing with this stack, # you need uncomment following line. Please see documentation at diff --git a/deployments/examples/ocis_traefik/config/ocis/entrypoint-override.sh b/deployments/examples/ocis_traefik/config/ocis/entrypoint-override.sh index c1f96fae4e..b5befa04aa 100644 --- a/deployments/examples/ocis_traefik/config/ocis/entrypoint-override.sh +++ b/deployments/examples/ocis_traefik/config/ocis/entrypoint-override.sh @@ -1,24 +1,5 @@ #!/bin/sh - set -e -ocis server& -sleep 10 - -echo "##################################################" -echo "change default secrets:" - -# IDP -IDP_USER_UUID=$(ocis accounts list | grep "| Kopano IDP " | egrep '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}' -o) -echo " IDP user UUID: $IDP_USER_UUID" -ocis accounts update --password $IDP_LDAP_BIND_PASSWORD $IDP_USER_UUID - -# REVA -REVA_USER_UUID=$(ocis accounts list | grep " | Reva Inter " | egrep '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}' -o) -echo " Reva user UUID: $REVA_USER_UUID" -ocis accounts update --password $STORAGE_LDAP_BIND_PASSWORD $REVA_USER_UUID - -echo "default secrets changed" -echo "##################################################" - -wait # wait for oCIS to exit +ocis init || true # will only initialize once +ocis server diff --git a/deployments/examples/ocis_traefik/docker-compose.yml b/deployments/examples/ocis_traefik/docker-compose.yml index 35fc4756cf..fc1133e5dc 100644 --- a/deployments/examples/ocis_traefik/docker-compose.yml +++ b/deployments/examples/ocis_traefik/docker-compose.yml @@ -53,21 +53,17 @@ services: OCIS_URL: https://${OCIS_DOMAIN:-ocis.owncloud.test} OCIS_LOG_LEVEL: ${OCIS_LOG_LEVEL:-error} # make oCIS less verbose PROXY_TLS: "false" # do not use SSL between Traefik and oCIS - # change default secrets - IDP_LDAP_BIND_PASSWORD: ${IDP_LDAP_BIND_PASSWORD:-idp} - STORAGE_LDAP_BIND_PASSWORD: ${STORAGE_LDAP_BIND_PASSWORD:-reva} - OCIS_JWT_SECRET: ${OCIS_JWT_SECRET:-Pive-Fumkiu4} - STORAGE_TRANSFER_SECRET: ${STORAGE_TRANSFER_SECRET:-replace-me-with-a-transfer-secret} - OCIS_MACHINE_AUTH_API_KEY: ${OCIS_MACHINE_AUTH_API_KEY:-change-me-please} # INSECURE: needed if oCIS / Traefik is using self generated certificates OCIS_INSECURE: "${INSECURE:-false}" # basic auth (not recommended, but needed for eg. WebDav clients that do not support OpenID Connect) PROXY_ENABLE_BASIC_AUTH: "${PROXY_ENABLE_BASIC_AUTH:-false}" + # admin user password + IDM_ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" # this overrides the admin password from the configuration file # demo users - ACCOUNTS_DEMO_USERS_AND_GROUPS: "${DEMO_USERS:-false}" # deprecated, remove after switching to LibreIDM IDM_CREATE_DEMO_USERS: "${DEMO_USERS:-false}" volumes: - ./config/ocis/entrypoint-override.sh:/entrypoint-override.sh + - ocis-config:/etc/ocis - ocis-data:/var/lib/ocis labels: - "traefik.enable=true" @@ -82,7 +78,9 @@ services: volumes: certs: + ocis-config: ocis-data: + networks: ocis-net: diff --git a/docs/extensions/accounts/tests.md b/docs/extensions/accounts/tests.md index 07de8e5dc3..5fdb2b5496 100644 --- a/docs/extensions/accounts/tests.md +++ b/docs/extensions/accounts/tests.md @@ -19,9 +19,10 @@ Make sure you've cloned the [web frontend repo](https://github.com/owncloud/web/ {{< hint info >}} For now, an IDP configuration file gets generated once and will fail upon changing the oCIS url as done below. To avoid any clashes, remove this file before starting the tests: -``` +```bash rm ~/.ocis/idp/identifier-registration.yaml ``` + {{< /hint >}} ### In the web repo @@ -30,7 +31,7 @@ rm ~/.ocis/idp/identifier-registration.yaml Install dependencies and bundle the frontend with a watcher by running -``` +```bash yarn && yarn build:w ``` @@ -40,7 +41,7 @@ If you skip the step above, the currently bundled frontend from the oCIS binary Start the necessary acceptance test services by using Docker (Compose): -``` +```bash docker compose up selenium middleware-ocis vnc ``` @@ -50,7 +51,7 @@ docker compose up selenium middleware-ocis vnc Navigate into the accounts service via `cd ../accounts/` and install dependencies and build the bundled accounts UI with a watcher by running -``` +```bash yarn && yarn watch ``` @@ -58,13 +59,14 @@ yarn && yarn watch Navigate into the oCIS directory inside the oCIS repository and build the oCIS binary by running -``` +```bash make clean build ``` Then, start oCIS from the binary via -``` +```bash +./bin/ocis init OCIS_URL=https://host.docker.internal:9200 OCIS_INSECURE=true PROXY_ENABLE_BASIC_AUTH=true WEB_UI_CONFIG=../../web/dev/docker/ocis.web.config.json ./bin/ocis server ``` @@ -78,6 +80,6 @@ If you want visual feedback on the test run, visit http://host.docker.internal:6 Navigate into the accounts service via `cd ../accounts/` and start the acceptance tests by running -``` +```bash SERVER_HOST=https://host.docker.internal:9200 BACKEND_HOST=https://host.docker.internal:9200 RUN_ON_OCIS=true NODE_TLS_REJECT_UNAUTHORIZED=0 WEB_PATH=../../web WEB_UI_CONFIG=../../web/tests/drone/config-ocis.json MIDDLEWARE_HOST=http://host.docker.internal:3000 ./ui/tests/run-acceptance-test.sh ./ui/tests/acceptance/features/ ``` diff --git a/docs/extensions/settings/tests.md b/docs/extensions/settings/tests.md index 06a4b3fb5f..b07ae58739 100644 --- a/docs/extensions/settings/tests.md +++ b/docs/extensions/settings/tests.md @@ -19,9 +19,10 @@ Make sure you've cloned the [web frontend repo](https://github.com/owncloud/web/ {{< hint info >}} For now, an IDP configuration file gets generated once and will fail upon changing the oCIS url as done below. To avoid any clashes, remove this file before starting the tests: -``` +```bash rm ~/.ocis/idp/identifier-registration.yaml ``` + {{< /hint >}} ### In the web repo @@ -30,7 +31,7 @@ rm ~/.ocis/idp/identifier-registration.yaml Install dependencies and bundle the frontend with a watcher by running -``` +```bash yarn && yarn build:w ``` @@ -40,7 +41,7 @@ If you skip the step above, the currently bundled frontend from the oCIS binary Start the necessary acceptance test services by using Docker (Compose): -``` +```bash docker compose up selenium middleware-ocis vnc ``` @@ -50,7 +51,7 @@ docker compose up selenium middleware-ocis vnc Navigate into the settings service via `cd ../settings/` and install dependencies and build the bundled settings UI with a watcher by running -``` +```bash yarn && yarn watch ``` @@ -58,13 +59,14 @@ yarn && yarn watch Navigate into the oCIS directory inside the oCIS repository and build the oCIS binary by running -``` +```bash make clean build ``` Then, start oCIS from the binary via -``` +```bash +ocis init OCIS_URL=https://host.docker.internal:9200 OCIS_INSECURE=true PROXY_ENABLE_BASIC_AUTH=true WEB_UI_CONFIG=../../web/dev/docker/ocis.web.config.json ./bin/ocis server ``` @@ -78,6 +80,6 @@ If you want visual feedback on the test run, visit http://host.docker.internal:6 Navigate into the settings service via `cd ../settings/` and start the acceptance tests by running -``` +```bash SERVER_HOST=https://host.docker.internal:9200 BACKEND_HOST=https://host.docker.internal:9200 RUN_ON_OCIS=true NODE_TLS_REJECT_UNAUTHORIZED=0 WEB_PATH=../../web WEB_UI_CONFIG=../../web/tests/drone/config-ocis.json MIDDLEWARE_HOST=http://host.docker.internal:3000 ./ui/tests/run-acceptance-test.sh ./ui/tests/acceptance/features/ ``` diff --git a/docs/helpers/example-config-generator.go.tmpl b/docs/helpers/example-config-generator.go.tmpl index 6e40721c1c..277cfdc9dc 100644 --- a/docs/helpers/example-config-generator.go.tmpl +++ b/docs/helpers/example-config-generator.go.tmpl @@ -22,9 +22,7 @@ func main() { {{- 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) + c := pkg{{$key}}.FullDefaultConfig() yml, err := yaml.Marshal(c) if err != nil { log.Fatalf("Marshalling yaml for pkg0 failed: %s\n", err) @@ -50,4 +48,3 @@ func main() { } } } - diff --git a/docs/ocis/deployment/_index.md b/docs/ocis/deployment/_index.md index e3fc175fda..7da501f392 100644 --- a/docs/ocis/deployment/_index.md +++ b/docs/ocis/deployment/_index.md @@ -27,38 +27,7 @@ oCIS deployments are super simple, yet there are many configurations possible fo ## Secure an oCIS instance -### Change default secrets -oCIS uses two system users which are needed for being operational: -- Reva Inter Operability Platform (bc596f3c-c955-4328-80a0-60d018b4ad57) -- Kopano IDP (820ba2a1-3f54-4538-80a4-2d73007e30bf) +oCIS no longer has any default secrets in versions later than oCIS 1.20.0. Therefore you're no +longer able to start oCIS without generating / setting all needed secrets. -Both have simple default passwords which need to be changed. Currently, changing a password is only possible on the command line. You need to run `ocis accounts update --password ` for both users. - -The new password for the Reva Inter Operability Platform user must be made available to oCIS by using the environment variable `STORAGE_LDAP_BIND_PASSWORD`. The same applies to the new Kopano IDP user password, which needs to be made available to oCIS in `IDP_LDAP_BIND_PASSWORD`. - -Furthermore, oCIS uses a shared secret to sign JWT tokens for inter service authorization, which also needs to be changed by the user. -You can change it by setting the `OCIS_JWT_SECRET` environment variable for oCIS to a random string. - -Another is used secret for singing JWT tokens for uploads and downloads, which also needs to be changed by the user. -You can change it by setting the `STORAGE_TRANSFER_SECRET` environment variable for oCIS to a random string. - -One more secret is used for machine auth, so that external applications can authenticate with an API key. -You can change it by setting the `OCIS_MACHINE_AUTH_API_KEY` environment variable for oCIS to a random string. - -### Delete demo users - -{{< hint info >}} -Before deleting the demo users mentioned below, you must create a new account for yourself and assign it to the administrator role. - -By default, oCIS doesn't create any demo users. During the first startup, it generates only the admin and one user for IDP and Reva respectively. -{{< /hint >}} - -oCIS ships with a few demo users besides the system users: -- Admin (ddc2004c-0977-11eb-9d3f-a793888cd0f8) -- Albert Einstein (4c510ada-c86b-4815-8820-42cdf82c3d51) -- Richard Feynman (932b4540-8d16-481e-8ef4-588e4b6b151c) -- Maurice Moss (058bff95-6708-4fe5-91e4-9ea3d377588b) -- Marie Curie (f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c) - -You can view them in ownCloud Web if you log in as Admin user or list them by running `ocis accounts list`. -After adding your own user it is safe to delete the demo users in the web UI or with the command `ocis accounts remove `. Please do not delete the system users (see [change default secrets]({{< ref "./#change-default-secrets" >}})) or oCIS will not function properly anymore. +The recommended way is to use `ocis init` for that. It will generate a secure config file for you. diff --git a/docs/ocis/deployment/basic-remote-setup.md b/docs/ocis/deployment/basic-remote-setup.md index eaa95ac702..461cb5b4b5 100644 --- a/docs/ocis/deployment/basic-remote-setup.md +++ b/docs/ocis/deployment/basic-remote-setup.md @@ -15,6 +15,8 @@ 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 +Initialize the oCIS configuration by running `./bin/ocis init`. + 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. @@ -23,10 +25,6 @@ In `$HOME/.ocis/idp` is a file `identifier-registration.yaml`. It is used to con 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 >}} -oCIS is currently in a Tech Preview state and is shipped with demo users. In order to secure your oCIS instances please follow following guide: [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}) -{{< /hint >}} - For the following examples you need to have the oCIS binary in your current working directory, we assume it is named `ocis` and it needs to be marked as executable. See [Getting Started]({{< ref "../getting-started/#binaries" >}}) for where to get the binary from. ### Using automatically generated certificates diff --git a/docs/ocis/deployment/oc10_ocis_parallel.md b/docs/ocis/deployment/oc10_ocis_parallel.md index d5ff6e72e4..d87f233ae5 100644 --- a/docs/ocis/deployment/oc10_ocis_parallel.md +++ b/docs/ocis/deployment/oc10_ocis_parallel.md @@ -122,8 +122,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oC10 and oCIS frontend in `CLOUD_DOMAIN=`, e.g. `CLOUD_DOMAIN=cloud.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - By default ownCloud 10 will be started in the `latest` version. If you want to start a specific version of oCIS set the version to `OC10_DOCKER_TAG=`. Available versions can be found on [Docker Hub](https://hub.docker.com/r/owncloud/ocis/tags?page=1&ordering=last_updated). You can switch the default application of ownCloud 10 by setting`OWNCLOUD_DEFAULT_APP=files` in oder to have the classic UI as frontend, which is also the default. If you prefer ownCloud Web as the default application in ownCloud 10 just set `OWNCLOUD_DEFAULT_APP=web`. diff --git a/docs/ocis/deployment/ocis_hello.md b/docs/ocis/deployment/ocis_hello.md index afc6e441c1..312939a73a 100644 --- a/docs/ocis/deployment/ocis_hello.md +++ b/docs/ocis/deployment/ocis_hello.md @@ -95,8 +95,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oCIS frontend in `OCIS_DOMAIN=`, e.g. `OCIS_DOMAIN=ocis.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - By default the oCIS Hello extension will be started in the `latest` version. If you want to start a specific version of oCIS Hello set the version to `OCIS_HELLO_DOCKER_TAG=`. Available versions can be found on [Docker Hub](https://hub.docker.com/r/owncloud/ocis-hello/tags?page=1&ordering=last_updated). Now you have configured everything and can save the file. diff --git a/docs/ocis/deployment/ocis_individual_services.md b/docs/ocis/deployment/ocis_individual_services.md index ab2bebe9b3..718e5291a4 100644 --- a/docs/ocis/deployment/ocis_individual_services.md +++ b/docs/ocis/deployment/ocis_individual_services.md @@ -91,8 +91,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oCIS frontend in `OCIS_DOMAIN=`, e.g. `OCIS_DOMAIN=ocis.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - You also can run more than one instance of the service by setting `OCIS_SCALE` to number greater than one. Now you have configured everything and can save the file. diff --git a/docs/ocis/deployment/ocis_keycloak.md b/docs/ocis/deployment/ocis_keycloak.md index 7495f661f5..5708569e2a 100644 --- a/docs/ocis/deployment/ocis_keycloak.md +++ b/docs/ocis/deployment/ocis_keycloak.md @@ -108,8 +108,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) If you want to change the OIDC client id of th ownCloud Web frontend, you can do this by setting the name to `OCIS_OIDC_CLIENT_ID=`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - Set your domain for the Keycloak administration panel and authentication endpoints to `KEYCLOAK_DOMAIN=` e.g. `KEYCLOAK_DOMAIN=keycloak.owncloud.test`. Changing the used Keycloak realm can be done by setting `KEYCLOAK_REALM=`. This defaults to the oCIS realm `KEYCLOAK_REALM=oCIS`. The oCIS realm will be automatically imported on startup and includes our demo users. diff --git a/docs/ocis/deployment/ocis_ldap.md b/docs/ocis/deployment/ocis_ldap.md index 7b0bea3354..8ec958451a 100644 --- a/docs/ocis/deployment/ocis_ldap.md +++ b/docs/ocis/deployment/ocis_ldap.md @@ -93,8 +93,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oCIS frontend in `OCIS_DOMAIN=`, e.g. `OCIS_DOMAIN=cloud.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - The OpenLDAP server in this example deployment has an admin users, which is also used as bind user in order to keep these examples simple. You can change the default password "admin" to a different one by setting it to `LDAP_ADMIN_PASSWORD=...`. Set your domain for the LDAP manager UI in `LDAP_MANAGER_DOMAIN=`, e.g. `ldap.owncloud.test`. diff --git a/docs/ocis/deployment/ocis_s3.md b/docs/ocis/deployment/ocis_s3.md index d98617aee6..38c2d9ddf2 100644 --- a/docs/ocis/deployment/ocis_s3.md +++ b/docs/ocis/deployment/ocis_s3.md @@ -104,8 +104,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oCIS frontend in `OCIS_DOMAIN=`, e.g. `OCIS_DOMAIN=ocis.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - Set your domain for the MinIO frontend in `MINIO_DOMAIN=`, e.g. `MINIO_DOMAIN=minio.owncloud.test`. If you are using other S3-compatible providers you need to configure the respective endpoint here. If you like you can change the default name of the S3 bucket by setting `MINIO_BUCKET=` to a different value. diff --git a/docs/ocis/deployment/ocis_traefik.md b/docs/ocis/deployment/ocis_traefik.md index a672577e2c..ee6851d108 100644 --- a/docs/ocis/deployment/ocis_traefik.md +++ b/docs/ocis/deployment/ocis_traefik.md @@ -88,8 +88,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oCIS frontend in `OCIS_DOMAIN=`, e.g. `OCIS_DOMAIN=ocis.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - Now you have configured everything and can save the file. * Start the docker stack diff --git a/docs/ocis/deployment/ocis_wopi.md b/docs/ocis/deployment/ocis_wopi.md index 10c5fd04d3..99f9713918 100644 --- a/docs/ocis/deployment/ocis_wopi.md +++ b/docs/ocis/deployment/ocis_wopi.md @@ -130,8 +130,6 @@ See also [example server setup]({{< ref "preparing_server" >}}) Set your domain for the oCIS frontend in `OCIS_DOMAIN=`, e.g. `OCIS_DOMAIN=ocis.owncloud.test`. - You also must override the default secrets in `IDP_LDAP_BIND_PASSWORD`, `STORAGE_LDAP_BIND_PASSWORD`, `OCIS_JWT_SECRET`, `STORAGE_TRANSFER_SECRET` and `OCIS_MACHINE_AUTH_API_KEY` in order to secure your oCIS instance. Choose some random strings e.g. from the output of `openssl rand -base64 32`. For more information see [secure an oCIS instance]({{< ref "./#secure-an-ocis-instance" >}}). - By default the CS3Org WOPI server will also be started in the `latest` version. If you want to start a specific version of it, you can set the version to `WOPISERVER_DOCKER_TAG=`. Available versions can be found on [Docker Hub](https://hub.docker.com/r/cs3org/wopiserver/tags?page=1&ordering=last_updated). Set your domain for the CS3Org WOPI server in `WOPISERVER_DOMAIN=`, where all office suites can download the files via the WOPI protocol. diff --git a/docs/ocis/deployment/systemd.md b/docs/ocis/deployment/systemd.md index d37d380f40..55d723e046 100644 --- a/docs/ocis/deployment/systemd.md +++ b/docs/ocis/deployment/systemd.md @@ -39,11 +39,10 @@ WantedBy=multi-user.target For reasons of simplicity we are using the root user and group to run oCIS which is not recommended. Please use a non-root user in production environments and modify the oCIS service definition accordingly. - In the service definition we referenced `/etc/ocis/ocis.env` as our file containing environment variables for the oCIS process. In order to create the file we need first to create the folder `/etc/ocis/` and then we can add the actual `/etc/ocis/ocis.env` with following content: -``` +```bash OCIS_URL=https://some-hostname-or-ip:9200 PROXY_HTTP_ADDR=0.0.0.0:9200 OCIS_INSECURE=false @@ -60,9 +59,10 @@ Please change your `OCIS_URL` in order to reflect your actual deployment. If you oCIS will store all data in `/var/lib/ocis`, because we configured it so by setting `OCIS_BASE_DATA_PATH`. Therefore you need to create that directory and make it accessible to the user, you use to start oCIS. - ## Starting the oCIS service +Initialize the oCIS configuration by running `ocis init --config-path /etc/ocis`. + You can enable oCIS now by running `systemctl enable --now ocis`. It will ensure that oCIS also is restarted after a reboot of the host. If you need to restart oCIS because of configuration changes in `/etc/ocis/ocis.env`, run `systemctl restart ocis`. diff --git a/docs/ocis/development/testing.md b/docs/ocis/development/testing.md index 58270b65f1..1439e67c6c 100644 --- a/docs/ocis/development/testing.md +++ b/docs/ocis/development/testing.md @@ -89,7 +89,7 @@ We are using the ownCloud 10 acceptance test suite against oCIS. All you need to do to get the acceptance tests is check out the core repo: -``` +```bash git clone https://github.com/owncloud/core.git ``` @@ -97,7 +97,8 @@ git clone https://github.com/owncloud/core.git To start ocis: -``` +```bash +ocis init OCIS_INSECURE=true PROXY_ENABLE_BASIC_AUTH=true bin/ocis server ``` @@ -108,12 +109,13 @@ OCIS_INSECURE=true PROXY_ENABLE_BASIC_AUTH=true bin/ocis server First we will need to clone the testing app in owncloud which contains the skeleton files required for running the tests. In the ownCloud 10 core clone the testing app with the following command: -``` +```bash git clone https://github.com/owncloud/testing apps/testing ``` Then run the api acceptance tests with the following command from the root of the ownCloud 10 core repository: -``` + +```bash make test-acceptance-api \ TEST_SERVER_URL=https://localhost:9200 \ TEST_OCIS=true \ @@ -153,7 +155,7 @@ If you want to work on a specific issue E.g.: - ``` + ```bash make test-acceptance-api \ TEST_SERVER_URL=https://localhost:9200 \ TEST_OCIS=true \ @@ -174,7 +176,8 @@ If you want to work on a specific issue Instruction on setup is available [here](https://owncloud.dev/ocis/deployment/oc10_ocis_parallel/#local-setup) Edit the `.env` file and uncomment this line: -``` + +```bash COMPOSE_FILE=docker-compose.yml:testing/docker-compose-additions.yml ``` diff --git a/docs/ocis/getting-started/_index.md b/docs/ocis/getting-started/_index.md index 0838cafdd1..5a31560b83 100644 --- a/docs/ocis/getting-started/_index.md +++ b/docs/ocis/getting-started/_index.md @@ -42,14 +42,17 @@ curl https://download.owncloud.com/ocis/ocis/stable/1.20.0/ocis-1.20.0-linux-amd # make binary executable chmod +x ocis +# initialize a minimal oCIS configuration +./ocis init + # run with demo users -OCIS_INSECURE=true ACCOUNTS_DEMO_USERS_AND_GROUPS=true ./ocis server +IDM_CREATE_DEMO_USERS=true ./ocis server ``` The default primary storage location is `~/.ocis` or `/var/lib/ocis` depending on the packaging format and your operating system user. You can change that value by configuration. {{< hint info >}} -When you're using oCIS with self-signed certificates, you need to set the environment variable `OCIS_INSECURE=true`, in order to make oCIS work. +When you're using oCIS with self-signed certificates, you need to answer the the question for certificate checking with "yes" or set the environment variable `OCIS_INSECURE=true`, in order to make oCIS work. {{< /hint >}} {{< hint warning >}} @@ -64,7 +67,8 @@ The `latest` tag always reflects the current master branch. ```console docker pull owncloud/ocis -docker run --rm -ti -p 9200:9200 -e OCIS_INSECURE=true -e ACCOUNTS_DEMO_USERS_AND_GROUPS=true owncloud/ocis +docker run --rm -it -v ocis-config:/etc/ocis owncloud/ocis init +docker run --rm -p 9200:9200 -v ocis-config:/etc/ocis -v ocis-data:/var/lib/ocis -e IDM_CREATE_DEMO_USERS=true owncloud/ocis ``` {{< hint info >}} @@ -72,11 +76,11 @@ When you're using oCIS with self-signed certificates, you need to set the enviro {{< /hint >}} {{< hint warming >}} -When you're creating the [demo users]({{< ref "./demo-users" >}}) by setting `ACCOUNTS_DEMO_USERS_AND_GROUPS=true`, you need to be sure that this instance is not used in production because the passwords are public. +When you're creating the [demo users]({{< ref "./demo-users" >}}) by setting `IDM_CREATE_DEMO_USERS=true`, you need to be sure that this instance is not used in production because the passwords are public. {{< /hint >}} {{< hint warning >}} -In order to persist your data, you need to mount a docker volume or create a host bind-mount at `/var/lib/ocis`, for example with: `-v /some/host/dir:/var/lib/ocis` +We are using named volumes for the oCIS configuration and oCIS data in the above example (`-v ocis-config:/etc/ocis -v ocis-data:/var/lib/ocis`). You could instead also use host bind-mounts instead, eg. `-v /some/host/dir:/var/lib/ocis`. You cannot use bind mounts on MacOS, since extended attributes are not supported ([owncloud/ocis#182](https://github.com/owncloud/ocis/issues/182), [moby/moby#1070](https://github.com/moby/moby/issues/1070)). {{< /hint >}} @@ -91,6 +95,12 @@ Open [https://localhost:9200](https://localhost:9200) and [login using one of th The oCIS single binary contains multiple extensions and the `ocis` command helps you to manage them. You already used `ocis server` to run all available extensions in the [Run oCIS]({{< ref "#run-ocis" >}}) section. We now will show you some more management commands, which you may also explore by typing `ocis --help` or going to the [docs]({{< ref "../config" >}}). +To initialize the oCIS configuration: + +{{< highlight txt >}} +ocis init +{{< / highlight >}} + To start oCIS server: {{< highlight txt >}} diff --git a/docs/ocis/getting-started/demo-users.md b/docs/ocis/getting-started/demo-users.md index 15179f98bd..470a1ed39d 100644 --- a/docs/ocis/getting-started/demo-users.md +++ b/docs/ocis/getting-started/demo-users.md @@ -16,13 +16,13 @@ To create the demo users, run the initial setup step with an additional environm 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 | -| katherine | gemini | katherine@example.org | space admin | users, sailing-lovers, physics-lovers, quantum-lovers | +| username | password | email | role | groups | +| --------- | ----------------------------------------- | --------------------- | ----------- | ----------------------------------------------------------------------- | +| admin | admin or the one generated by `ocis init` | 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 | space admin | 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" >}}). diff --git a/docs/ocis/storage-backends/dcfsnfs.md b/docs/ocis/storage-backends/dcfsnfs.md index 07e68fbf43..6ef13be37a 100644 --- a/docs/ocis/storage-backends/dcfsnfs.md +++ b/docs/ocis/storage-backends/dcfsnfs.md @@ -53,12 +53,11 @@ The oCIS server can be instructed to set up the decomposed FS at a certain path The test setup started an oCIS tech preview single binary release using this start command: -``` +```bash +ocis init OCIS_BASE_DATA_PATH=/mnt/ocisdata/ OCIS_LOG_LEVEL=debug OCIS_INSECURE=true PROXY_HTTP_ADDR=0.0.0.0:9200 OCIS_URL=https://hostname:9200 ./ocis-1.18.0-linux-amd64 server ``` This starts oCIS and a decomposed FS skeleton file system structure is set up on the NFS share. The oCIS instance is passing a smoke test. - - diff --git a/extensions/accounts/cmd/helper/defaultconfig/main.go b/extensions/accounts/cmd/helper/defaultconfig/main.go deleted file mode 100644 index f60d1525d1..0000000000 --- a/extensions/accounts/cmd/helper/defaultconfig/main.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "fmt" - - accountsdefaults "github.com/owncloud/ocis/extensions/accounts/pkg/config/defaults" - idpdefaults "github.com/owncloud/ocis/extensions/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)) -} diff --git a/extensions/accounts/pkg/command/health.go b/extensions/accounts/pkg/command/health.go index 2879462576..0590938e93 100644 --- a/extensions/accounts/pkg/command/health.go +++ b/extensions/accounts/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/accounts/pkg/command/server.go b/extensions/accounts/pkg/command/server.go index cad2406868..26fb0f1f49 100644 --- a/extensions/accounts/pkg/command/server.go +++ b/extensions/accounts/pkg/command/server.go @@ -25,7 +25,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/accounts/pkg/config/config.go b/extensions/accounts/pkg/config/config.go index 9b46d2dbf1..29c2ce7fe5 100644 --- a/extensions/accounts/pkg/config/config.go +++ b/extensions/accounts/pkg/config/config.go @@ -19,7 +19,7 @@ type Config struct { HTTP HTTP `yaml:"http"` GRPC GRPC `yaml:"grpc"` - TokenManager TokenManager `yaml:"token_manager"` + TokenManager *TokenManager `yaml:"token_manager"` Asset Asset `yaml:"asset"` Repo Repo `yaml:"repo"` @@ -36,11 +36,6 @@ type Asset struct { Path string `yaml:"path" env:"ACCOUNTS_ASSET_PATH" desc:"The path to the ui assets."` } -// TokenManager is the config for using the reva token manager -type TokenManager struct { - JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;ACCOUNTS_JWT_SECRET" desc:"The secret to mint jwt tokens."` -} - // Repo defines which storage implementation is to be used. type Repo struct { Backend string `yaml:"backend" env:"ACCOUNTS_STORAGE_BACKEND" desc:"Defines which storage implementation is to be used"` diff --git a/extensions/accounts/pkg/config/defaults/defaultconfig.go b/extensions/accounts/pkg/config/defaults/defaultconfig.go index d44ca4aafb..6aaea79f33 100644 --- a/extensions/accounts/pkg/config/defaults/defaultconfig.go +++ b/extensions/accounts/pkg/config/defaults/defaultconfig.go @@ -10,10 +10,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -44,10 +42,7 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "accounts", }, - Asset: config.Asset{}, - TokenManager: config.TokenManager{ - JWTSecret: "Pive-Fumkiu4", - }, + Asset: config.Asset{}, HashDifficulty: 11, DemoUsersAndGroups: false, Repo: config.Repo{ @@ -101,6 +96,14 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/accounts/pkg/config/parser/parse.go b/extensions/accounts/pkg/config/parser/parse.go index 91d47c19d8..b052fd59c3 100644 --- a/extensions/accounts/pkg/config/parser/parse.go +++ b/extensions/accounts/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/accounts/pkg/config" defaults "github.com/owncloud/ocis/extensions/accounts/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +30,12 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } return nil } diff --git a/extensions/accounts/pkg/config/reva.go b/extensions/accounts/pkg/config/reva.go new file mode 100644 index 0000000000..172786f6f1 --- /dev/null +++ b/extensions/accounts/pkg/config/reva.go @@ -0,0 +1,6 @@ +package config + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;ACCOUNTS_JWT_SECRET"` +} diff --git a/extensions/appprovider/pkg/command/command.go b/extensions/appprovider/pkg/command/command.go index 2c1399446f..f638e3c98c 100644 --- a/extensions/appprovider/pkg/command/command.go +++ b/extensions/appprovider/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" @@ -10,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/appprovider/pkg/config" + "github.com/owncloud/ocis/extensions/appprovider/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/log" @@ -24,6 +26,13 @@ func AppProvider(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "app-provider", Usage: "start appprovider for providing apps", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -92,8 +101,8 @@ func appProviderConfigFromStruct(c *cli.Context, cfg *config.Config) map[string] "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ @@ -114,7 +123,7 @@ func appProviderConfigFromStruct(c *cli.Context, cfg *config.Config) map[string] "app_url": cfg.Drivers.WOPI.AppURL, "insecure_connections": cfg.Drivers.WOPI.Insecure, "iop_secret": cfg.Drivers.WOPI.IopSecret, - "jwt_secret": cfg.JWTSecret, + "jwt_secret": cfg.TokenManager.JWTSecret, "wopi_url": cfg.Drivers.WOPI.WopiURL, }, }, diff --git a/extensions/appprovider/pkg/config/config.go b/extensions/appprovider/pkg/config/config.go index 72645eee81..9f0c0e9c55 100644 --- a/extensions/appprovider/pkg/config/config.go +++ b/extensions/appprovider/pkg/config/config.go @@ -8,16 +8,17 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool - ExternalAddr string - Driver string - Drivers Drivers + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` + ExternalAddr string `yaml:"external_addr"` + Driver string `yaml:"driver"` + Drivers Drivers `yaml:"drivers"` } type Tracing struct { diff --git a/extensions/appprovider/pkg/config/defaults/defaultconfig.go b/extensions/appprovider/pkg/config/defaults/defaultconfig.go index 332ce0dba4..978c6d2edb 100644 --- a/extensions/appprovider/pkg/config/defaults/defaultconfig.go +++ b/extensions/appprovider/pkg/config/defaults/defaultconfig.go @@ -2,13 +2,13 @@ package defaults import ( "github.com/owncloud/ocis/extensions/appprovider/pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" ) func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -27,9 +27,10 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "appprovider", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - Driver: "", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + Driver: "", Drivers: config.Drivers{ WOPI: config.WOPIDriver{}, }, @@ -59,8 +60,32 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { // nothing to sanitize here atm } + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/appprovider/pkg/config/parser/parse.go b/extensions/appprovider/pkg/config/parser/parse.go new file mode 100644 index 0000000000..ff554af475 --- /dev/null +++ b/extensions/appprovider/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/appprovider/pkg/config" + "github.com/owncloud/ocis/extensions/appprovider/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/appprovider/pkg/config/reva.go b/extensions/appprovider/pkg/config/reva.go new file mode 100644 index 0000000000..aec078b05a --- /dev/null +++ b/extensions/appprovider/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;APP_PROVIDER_JWT_SECRET"` +} diff --git a/extensions/audit/pkg/command/server.go b/extensions/audit/pkg/command/server.go index 2ace55644a..ad4ad4e175 100644 --- a/extensions/audit/pkg/command/server.go +++ b/extensions/audit/pkg/command/server.go @@ -22,7 +22,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/audit/pkg/config/defaults/defaultconfig.go b/extensions/audit/pkg/config/defaults/defaultconfig.go index 27b94a8147..f6ec2fb31e 100644 --- a/extensions/audit/pkg/config/defaults/defaultconfig.go +++ b/extensions/audit/pkg/config/defaults/defaultconfig.go @@ -6,10 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/audit/pkg/config/parser/parse.go b/extensions/audit/pkg/config/parser/parse.go index 7c9179761c..f34652a319 100644 --- a/extensions/audit/pkg/config/parser/parse.go +++ b/extensions/audit/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +29,9 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/extensions/audit/pkg/service/service_test.go b/extensions/audit/pkg/service/service_test.go index 6fb5dc1ea0..6d45dfde1a 100644 --- a/extensions/audit/pkg/service/service_test.go +++ b/extensions/audit/pkg/service/service_test.go @@ -297,8 +297,8 @@ var testCases = []struct { }, { Alias: "File created", SystemEvent: events.FileUploaded{ - FileID: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileCreated{} @@ -312,8 +312,8 @@ var testCases = []struct { }, { Alias: "File read", SystemEvent: events.FileDownloaded{ - FileID: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileRead{} @@ -327,8 +327,8 @@ var testCases = []struct { }, { Alias: "File trashed", SystemEvent: events.ItemTrashed{ - FileID: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileDeleted{} @@ -342,7 +342,7 @@ var testCases = []struct { }, { Alias: "File renamed", SystemEvent: events.ItemMoved{ - FileID: reference("sto-123", "iid-123", "./item"), + Ref: reference("sto-123", "iid-123", "./item"), OldReference: reference("sto-123", "iid-123", "./anotheritem"), Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, @@ -361,8 +361,8 @@ var testCases = []struct { }, { Alias: "File purged", SystemEvent: events.ItemPurged{ - FileID: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFilePurged{} @@ -376,7 +376,7 @@ var testCases = []struct { }, { Alias: "File restored", SystemEvent: events.ItemRestored{ - FileID: reference("sto-123", "iid-123", "./item"), + Ref: reference("sto-123", "iid-123", "./item"), Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva OldReference: reference("sto-123", "sto-123!iid-123/item", "./oldpath"), Key: "", @@ -396,9 +396,9 @@ var testCases = []struct { }, { Alias: "File version restored", SystemEvent: events.FileVersionRestored{ - FileID: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva - Key: "v1", + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Key: "v1", }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileVersionRestored{} diff --git a/extensions/auth-basic/pkg/command/command.go b/extensions/auth-basic/pkg/command/command.go index 7835e9f09f..cd08691a56 100644 --- a/extensions/auth-basic/pkg/command/command.go +++ b/extensions/auth-basic/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" "path/filepath" @@ -11,6 +12,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/auth-basic/pkg/config" + "github.com/owncloud/ocis/extensions/auth-basic/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/ldap" @@ -26,6 +28,13 @@ func AuthBasic(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "auth-basic", Usage: "start authprovider for basic auth", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -113,8 +122,8 @@ func authBasicConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]in "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/auth-basic/pkg/config/config.go b/extensions/auth-basic/pkg/config/config.go index e3706473cc..2632ac9b16 100644 --- a/extensions/auth-basic/pkg/config/config.go +++ b/extensions/auth-basic/pkg/config/config.go @@ -8,13 +8,14 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` AuthProvider string `yaml:"auth_provider" env:"AUTH_BASIC_AUTH_PROVIDER" desc:"The auth provider which should be used by the service"` AuthProviders AuthProviders `yaml:"auth_providers"` } @@ -63,7 +64,7 @@ type LDAPProvider struct { CACert string `env:"LDAP_CACERT;AUTH_BASIC_LDAP_CACERT"` Insecure bool `env:"LDAP_INSECURE;AUTH_BASIC_LDAP_INSECURE"` BindDN string `env:"LDAP_BIND_DN;AUTH_BASIC_LDAP_BIND_DN"` - BindPassword string `env:"LDAP_BIND_PASSWORD;AUTH_BASIC_LDAP_BIND_PASSWORD"` + BindPassword string `yaml:"bind_password" env:"LDAP_BIND_PASSWORD;AUTH_BASIC_LDAP_BIND_PASSWORD"` UserBaseDN string `env:"LDAP_USER_BASE_DN;AUTH_BASIC_LDAP_USER_BASE_DN"` GroupBaseDN string `env:"LDAP_GROUP_BASE_DN;AUTH_BASIC_LDAP_GROUP_BASE_DN"` UserScope string `env:"LDAP_USER_SCOPE;AUTH_BASIC_LDAP_USER_SCOPE"` diff --git a/extensions/auth-basic/pkg/config/defaults/defaultconfig.go b/extensions/auth-basic/pkg/config/defaults/defaultconfig.go index 309b132446..3bfbaf800f 100644 --- a/extensions/auth-basic/pkg/config/defaults/defaultconfig.go +++ b/extensions/auth-basic/pkg/config/defaults/defaultconfig.go @@ -9,9 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -30,9 +29,10 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "auth-basic", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - AuthProvider: "ldap", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + AuthProvider: "ldap", AuthProviders: config.AuthProviders{ LDAP: config.LDAPProvider{ URI: "ldaps://localhost:9235", @@ -48,7 +48,6 @@ func DefaultConfig() *config.Config { UserObjectClass: "inetOrgPerson", GroupObjectClass: "groupOfNames", BindDN: "uid=reva,ou=sysusers,o=libregraph-idm", - BindPassword: "reva", IDP: "https://localhost:9200", UserSchema: config.LDAPUserSchema{ ID: "ownclouduuid", @@ -67,7 +66,6 @@ func DefaultConfig() *config.Config { JSON: config.JSONProvider{}, OwnCloudSQL: config.OwnCloudSQLProvider{ DBUsername: "owncloud", - DBPassword: "secret", DBHost: "mysql", DBPort: 3306, DBName: "owncloud", @@ -103,6 +101,23 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + } func Sanitize(cfg *config.Config) { diff --git a/extensions/auth-basic/pkg/config/parser/parse.go b/extensions/auth-basic/pkg/config/parser/parse.go new file mode 100644 index 0000000000..de3b06d5c5 --- /dev/null +++ b/extensions/auth-basic/pkg/config/parser/parse.go @@ -0,0 +1,46 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/auth-basic/pkg/config" + "github.com/owncloud/ocis/extensions/auth-basic/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.AuthProviders.LDAP.BindPassword == "" && cfg.AuthProvider == "ldap" { + return shared.MissingLDAPBindPassword(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/auth-basic/pkg/config/reva.go b/extensions/auth-basic/pkg/config/reva.go new file mode 100644 index 0000000000..e01bce8ed7 --- /dev/null +++ b/extensions/auth-basic/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;AUTH_BASIC_JWT_SECRET"` +} diff --git a/extensions/auth-bearer/pkg/command/command.go b/extensions/auth-bearer/pkg/command/command.go index dd27a0b8e4..ea41172d27 100644 --- a/extensions/auth-bearer/pkg/command/command.go +++ b/extensions/auth-bearer/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" @@ -10,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/auth-bearer/pkg/config" + "github.com/owncloud/ocis/extensions/auth-bearer/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/log" @@ -24,6 +26,13 @@ func AuthBearer(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "auth-bearer", Usage: "start authprovider for bearer auth", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -94,8 +103,8 @@ func authBearerConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]i "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/auth-bearer/pkg/config/config.go b/extensions/auth-bearer/pkg/config/config.go index 0bc26ab120..984ac37984 100644 --- a/extensions/auth-bearer/pkg/config/config.go +++ b/extensions/auth-bearer/pkg/config/config.go @@ -8,13 +8,14 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` AuthProvider string `yaml:"auth_provider" env:"AUTH_BEARER_AUTH_PROVIDER" desc:"The auth provider which should be used by the service"` AuthProviders AuthProviders `yaml:"auth_providers"` } diff --git a/extensions/auth-bearer/pkg/config/defaults/defaultconfig.go b/extensions/auth-bearer/pkg/config/defaults/defaultconfig.go index 4ca3d0f5ca..59d0acd706 100644 --- a/extensions/auth-bearer/pkg/config/defaults/defaultconfig.go +++ b/extensions/auth-bearer/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -27,9 +26,10 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "auth-bearer", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - AuthProvider: "ldap", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + AuthProvider: "ldap", AuthProviders: config.AuthProviders{ OIDC: config.OIDCProvider{ Issuer: "https://localhost:9200", @@ -63,6 +63,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/auth-bearer/pkg/config/parser/parse.go b/extensions/auth-bearer/pkg/config/parser/parse.go new file mode 100644 index 0000000000..fc3a1c5020 --- /dev/null +++ b/extensions/auth-bearer/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/auth-bearer/pkg/config" + "github.com/owncloud/ocis/extensions/auth-bearer/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/auth-bearer/pkg/config/reva.go b/extensions/auth-bearer/pkg/config/reva.go new file mode 100644 index 0000000000..1615b97d00 --- /dev/null +++ b/extensions/auth-bearer/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;AUTH_BEARER_JWT_SECRET"` +} diff --git a/extensions/auth-machine/pkg/command/command.go b/extensions/auth-machine/pkg/command/command.go index 332c1ed865..1ab91220af 100644 --- a/extensions/auth-machine/pkg/command/command.go +++ b/extensions/auth-machine/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" @@ -10,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/auth-machine/pkg/config" + "github.com/owncloud/ocis/extensions/auth-machine/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/log" @@ -24,6 +26,13 @@ func AuthMachine(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "auth-machine", Usage: "start authprovider for machine auth", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -94,8 +103,8 @@ func authMachineConfigFromStruct(c *cli.Context, cfg *config.Config) map[string] "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ @@ -108,7 +117,7 @@ func authMachineConfigFromStruct(c *cli.Context, cfg *config.Config) map[string] "auth_managers": map[string]interface{}{ "machine": map[string]interface{}{ "api_key": cfg.AuthProviders.Machine.APIKey, - "gateway_addr": cfg.GatewayEndpoint, + "gateway_addr": cfg.Reva.Address, }, }, }, diff --git a/extensions/auth-machine/pkg/config/config.go b/extensions/auth-machine/pkg/config/config.go index 50a2db2c15..19ff424c9b 100644 --- a/extensions/auth-machine/pkg/config/config.go +++ b/extensions/auth-machine/pkg/config/config.go @@ -8,13 +8,14 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` AuthProvider string `yaml:"auth_provider" env:"AUTH_MACHINE_AUTH_PROVIDER" desc:"The auth provider which should be used by the service"` AuthProviders AuthProviders `yaml:"auth_providers"` } diff --git a/extensions/auth-machine/pkg/config/defaults/defaultconfig.go b/extensions/auth-machine/pkg/config/defaults/defaultconfig.go index 4a442d48b8..47b0f1a16a 100644 --- a/extensions/auth-machine/pkg/config/defaults/defaultconfig.go +++ b/extensions/auth-machine/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -27,14 +26,10 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "auth-machine", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - AuthProvider: "ldap", - AuthProviders: config.AuthProviders{ - Machine: config.MachineProvider{ - APIKey: "change-me-please", - }, + Reva: &config.Reva{ + Address: "127.0.0.1:9142", }, + AuthProvider: "ldap", } } @@ -61,6 +56,26 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.AuthProviders.Machine.APIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.AuthProviders.Machine.APIKey = cfg.Commons.MachineAuthAPIKey + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/auth-machine/pkg/config/parser/parse.go b/extensions/auth-machine/pkg/config/parser/parse.go new file mode 100644 index 0000000000..2eb535806b --- /dev/null +++ b/extensions/auth-machine/pkg/config/parser/parse.go @@ -0,0 +1,45 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/auth-machine/pkg/config" + "github.com/owncloud/ocis/extensions/auth-machine/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.AuthProviders.Machine.APIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + return nil +} diff --git a/extensions/auth-machine/pkg/config/reva.go b/extensions/auth-machine/pkg/config/reva.go new file mode 100644 index 0000000000..e81446d87f --- /dev/null +++ b/extensions/auth-machine/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;AUTH_MACHINE_JWT_SECRET"` +} diff --git a/extensions/frontend/pkg/command/command.go b/extensions/frontend/pkg/command/command.go index c1a4c39c27..d14917d1c6 100644 --- a/extensions/frontend/pkg/command/command.go +++ b/extensions/frontend/pkg/command/command.go @@ -7,15 +7,14 @@ import ( "os" "path" "strconv" - "strings" "github.com/cs3org/reva/v2/cmd/revad/runtime" "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/frontend/pkg/config" + "github.com/owncloud/ocis/extensions/frontend/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" - "github.com/owncloud/ocis/ocis-pkg/conversions" "github.com/owncloud/ocis/ocis-pkg/log" "github.com/owncloud/ocis/ocis-pkg/sync" "github.com/owncloud/ocis/ocis-pkg/tracing" @@ -28,11 +27,12 @@ func Frontend(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "frontend", Usage: "start frontend service", - Before: func(c *cli.Context) error { - if err := loadUserAgent(c, cfg); err != nil { - return err + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) } - return nil + return err }, Action: func(c *cli.Context) error { logCfg := cfg.Logging @@ -53,13 +53,6 @@ func Frontend(cfg *config.Config) *cli.Command { uuid := uuid.Must(uuid.NewV4()) pidFile := path.Join(os.TempDir(), "revad-"+c.Command.Name+"-"+uuid.String()+".pid") - // pregenerate list of valid localhost ports for the desktop redirect_uri - // TODO use custom scheme like "owncloud://localhost/user/callback" tracked in - var desktopRedirectURIs [65535 - 1024]string - for port := 0; port < len(desktopRedirectURIs); port++ { - desktopRedirectURIs[port] = fmt.Sprintf("http://localhost:%d", (port + 1024)) - } - archivers := []map[string]interface{}{ { "enabled": true, @@ -156,8 +149,8 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, // Todo or address? + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, // Todo or address? "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "http": map[string]interface{}{ @@ -194,13 +187,13 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s "insecure": true, }, "ocs": map[string]interface{}{ - "storage_registry_svc": cfg.GatewayEndpoint, + "storage_registry_svc": cfg.Reva.Address, "share_prefix": cfg.OCS.SharePrefix, "home_namespace": cfg.OCS.HomeNamespace, "resource_info_cache_ttl": cfg.OCS.ResourceInfoCacheTTL, "prefix": cfg.OCS.Prefix, "additional_info_attribute": cfg.OCS.AdditionalInfoAttribute, - "machine_auth_apikey": cfg.AuthMachine.APIKey, + "machine_auth_apikey": cfg.MachineAuthAPIKey, "cache_warmup_driver": cfg.OCS.CacheWarmupDriver, "cache_warmup_drivers": map[string]interface{}{ "cbox": map[string]interface{}{ @@ -210,7 +203,7 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s "db_port": cfg.OCS.CacheWarmupDrivers.CBOX.DBPort, "db_name": cfg.OCS.CacheWarmupDrivers.CBOX.DBName, "namespace": cfg.OCS.CacheWarmupDrivers.CBOX.Namespace, - "gatewaysvc": cfg.GatewayEndpoint, + "gatewaysvc": cfg.Reva.Address, }, }, "config": map[string]interface{}{ @@ -295,8 +288,10 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s }, }, "spaces": map[string]interface{}{ - "version": "0.0.1", - "enabled": cfg.EnableProjectSpaces, + "version": "0.0.1", + "enabled": cfg.EnableProjectSpaces || cfg.EnableShareJail, + "projects": cfg.EnableProjectSpaces, + "share_jail": cfg.EnableShareJail, }, }, "version": map[string]interface{}{ @@ -313,31 +308,6 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s } } -// loadUserAgent reads the user-agent-whitelist-lock-in, since it is a string flag, and attempts to construct a map of -// "user-agent":"challenge" locks in for Reva. -// Modifies cfg. Spaces don't need to be trimmed as urfavecli takes care of it. User agents with spaces are valid. i.e: -// Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0 -// This function works by relying in our format of specifying [user-agent:challenge] and the fact that the user agent -// might contain ":" (colon), so the original string is reversed, split in two parts, by the time it is split we -// have the indexes reversed and the tuple is in the format of [challenge:user-agent], then the same process is applied -// in reverse for each individual part -func loadUserAgent(c *cli.Context, cfg *config.Config) error { - cfg.Middleware.Auth.CredentialsByUserAgent = make(map[string]string) - locks := c.StringSlice("user-agent-whitelist-lock-in") - - for _, v := range locks { - vv := conversions.Reverse(v) - parts := strings.SplitN(vv, ":", 2) - if len(parts) != 2 { - return fmt.Errorf("unexpected config value for user-agent lock-in: %v, expected format is user-agent:challenge", v) - } - - cfg.Middleware.Auth.CredentialsByUserAgent[conversions.Reverse(parts[1])] = conversions.Reverse(parts[0]) - } - - return nil -} - // FrontendSutureService allows for the storage-frontend command to be embedded and supervised by a suture supervisor tree. type FrontendSutureService struct { cfg *config.Config diff --git a/extensions/frontend/pkg/config/config.go b/extensions/frontend/pkg/config/config.go index fd9d1c99a8..a82e1fd42d 100644 --- a/extensions/frontend/pkg/config/config.go +++ b/extensions/frontend/pkg/config/config.go @@ -8,31 +8,36 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` HTTP HTTPConfig `yaml:"http"` // JWTSecret used to verify reva access token - JWTSecret string `yaml:"jwt_secret"` - GatewayEndpoint string - SkipUserGroupsInToken bool - EnableFavorites bool `yaml:"favorites"` - EnableProjectSpaces bool + TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"` + + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;FRONTEND_MACHINE_AUTH_API_KEY"` + + SkipUserGroupsInToken bool `yaml:"skip_users_groups_in_token"` + + EnableFavorites bool `yaml:"favorites"` + EnableProjectSpaces bool `yaml:"enable_project_spaces" env:"FRONTEND_ENABLE_PROJECT_SPACES" desc:"Indicates to clients that project spaces are supposed to be made available."` + EnableShareJail bool `yaml:"enable_share_jail" env:"FRONTEND_ENABLE_SHARE_JAIL" desc:"Indicates to clients that the share jail is supposed to be used."` UploadMaxChunkSize int `yaml:"upload_max_chunk_size"` UploadHTTPMethodOverride string `yaml:"upload_http_method_override"` DefaultUploadProtocol string `yaml:"default_upload_protocol"` - TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"` - PublicURL string `yaml:"public_url" env:"OCIS_URL;FRONTEND_PUBLIC_URL"` - Archiver Archiver - AppProvider AppProvider - DataGateway DataGateway - OCS OCS - AuthMachine AuthMachine - Checksums Checksums + PublicURL string `yaml:"public_url" env:"OCIS_URL;FRONTEND_PUBLIC_URL"` - Middleware Middleware + Archiver Archiver `yaml:"archiver"` + AppProvider AppProvider `yaml:"app_provider"` + DataGateway DataGateway `yaml:"data_gateway"` + OCS OCS `yaml:"ocs"` + Checksums Checksums `yaml:"checksums"` + + Middleware Middleware `yaml:"middleware"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;FRONTEND_TRACING_ENABLED" desc:"Activates tracing."` @@ -72,25 +77,25 @@ type Middleware struct { // Auth configures reva http auth middleware. type Auth struct { - CredentialsByUserAgent map[string]string `yaml:"credentials_by_user_agenr"` + CredentialsByUserAgent map[string]string `yaml:"credentials_by_user_agent"` } type Archiver struct { - MaxNumFiles int64 `yaml:"max_num_files"` - MaxSize int64 `yaml:"max_size"` - Prefix string - Insecure bool `env:"OCIS_INSECURE;FRONTEND_ARCHIVER_INSECURE"` + MaxNumFiles int64 `yaml:"max_num_files"` + MaxSize int64 `yaml:"max_size"` + Prefix string `yaml:"-"` + Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;FRONTEND_ARCHIVER_INSECURE"` } type AppProvider struct { ExternalAddr string `yaml:"external_addr"` Driver string `yaml:"driver"` // WopiDriver WopiDriver `yaml:"wopi_driver"` - AppsURL string `yaml:"apps_url"` - OpenURL string `yaml:"open_url"` - NewURL string `yaml:"new_url"` - Prefix string - Insecure bool `env:"OCIS_INSECURE;FRONTEND_APPPROVIDER_INSECURE"` + AppsURL string `yaml:"-"` + OpenURL string `yaml:"-"` + NewURL string `yaml:"-"` + Prefix string `yaml:"-"` + Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;FRONTEND_APPPROVIDER_INSECURE"` } type DataGateway struct { @@ -120,10 +125,6 @@ type CBOXDriver struct { Namespace string } -type AuthMachine struct { - APIKey string `env:"OCIS_MACHINE_AUTH_API_KEY"` -} - type Checksums struct { SupportedTypes []string `yaml:"supported_types"` PreferredUploadType string `yaml:"preferred_upload_type"` diff --git a/extensions/frontend/pkg/config/defaults/defaultconfig.go b/extensions/frontend/pkg/config/defaults/defaultconfig.go index 182914b822..a1067f1eb5 100644 --- a/extensions/frontend/pkg/config/defaults/defaultconfig.go +++ b/extensions/frontend/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -28,15 +27,16 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "frontend", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, PublicURL: "https://localhost:9200", EnableFavorites: false, EnableProjectSpaces: true, + EnableShareJail: true, UploadMaxChunkSize: 1e+8, UploadHTTPMethodOverride: "", DefaultUploadProtocol: "tus", - TransferSecret: "replace-me-with-a-transfer-secret", Checksums: config.Checksums{ SupportedTypes: []string{"sha1", "md5", "adler32"}, PreferredUploadType: "", @@ -62,9 +62,6 @@ func DefaultConfig() *config.Config { AdditionalInfoAttribute: "{{.Mail}}", ResourceInfoCacheTTL: 0, }, - AuthMachine: config.AuthMachine{ - APIKey: "change-me-please", - }, Middleware: config.Middleware{ Auth: config.Auth{ CredentialsByUserAgent: map[string]string{}, @@ -96,6 +93,31 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.TransferSecret == "" && cfg.Commons != nil && cfg.Commons.TransferSecret != "" { + cfg.TransferSecret = cfg.Commons.TransferSecret + } + + if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } + } func Sanitize(cfg *config.Config) { diff --git a/extensions/frontend/pkg/config/parser/parse.go b/extensions/frontend/pkg/config/parser/parse.go new file mode 100644 index 0000000000..e2ff551a5c --- /dev/null +++ b/extensions/frontend/pkg/config/parser/parse.go @@ -0,0 +1,50 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/frontend/pkg/config" + "github.com/owncloud/ocis/extensions/frontend/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.TransferSecret == "" { + return shared.MissingRevaTransferSecretError(cfg.Service.Name) + } + + if cfg.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/frontend/pkg/config/reva.go b/extensions/frontend/pkg/config/reva.go new file mode 100644 index 0000000000..77484698f3 --- /dev/null +++ b/extensions/frontend/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;FRONTEND_JWT_SECRET"` +} diff --git a/extensions/gateway/pkg/command/command.go b/extensions/gateway/pkg/command/command.go index af5bb5e836..60440c2279 100644 --- a/extensions/gateway/pkg/command/command.go +++ b/extensions/gateway/pkg/command/command.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "flag" + "fmt" "io/ioutil" "os" "path" @@ -15,6 +16,7 @@ import ( "github.com/mitchellh/mapstructure" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/gateway/pkg/config" + "github.com/owncloud/ocis/extensions/gateway/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" "github.com/owncloud/ocis/extensions/storage/pkg/service/external" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" @@ -31,12 +33,12 @@ func Gateway(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "gateway", Usage: "start gateway", - Before: func(c *cli.Context) error { - if cfg.DataGatewayPublicURL == "" { - cfg.DataGatewayPublicURL = strings.TrimRight(cfg.FrontendPublicURL, "/") + "/data" + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) } - - return nil + return err }, Action: func(c *cli.Context) error { logCfg := cfg.Logging @@ -125,8 +127,8 @@ func gatewayConfigFromStruct(c *cli.Context, cfg *config.Config, logger log.Logg "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ @@ -136,9 +138,9 @@ func gatewayConfigFromStruct(c *cli.Context, cfg *config.Config, logger log.Logg "services": map[string]interface{}{ "gateway": map[string]interface{}{ // registries is located on the gateway - "authregistrysvc": cfg.GatewayEndpoint, - "storageregistrysvc": cfg.GatewayEndpoint, - "appregistrysvc": cfg.GatewayEndpoint, + "authregistrysvc": cfg.Reva.Address, + "storageregistrysvc": cfg.Reva.Address, + "appregistrysvc": cfg.Reva.Address, // user metadata is located on the users services "preferencessvc": cfg.UsersEndpoint, "userprovidersvc": cfg.UsersEndpoint, @@ -153,7 +155,7 @@ func gatewayConfigFromStruct(c *cli.Context, cfg *config.Config, logger log.Logg "share_folder": cfg.ShareFolder, // ShareFolder is the location where to create shares in the recipient's storage provider. // other "disable_home_creation_on_login": cfg.DisableHomeCreationOnLogin, - "datagateway": cfg.DataGatewayPublicURL, + "datagateway": strings.TrimRight(cfg.FrontendPublicURL, "/") + "/data", "transfer_shared_secret": cfg.TransferSecret, "transfer_expires": cfg.TransferExpires, "home_mapping": cfg.HomeMapping, diff --git a/extensions/gateway/pkg/config/config.go b/extensions/gateway/pkg/config/config.go index 740fa151f6..ca3555e721 100644 --- a/extensions/gateway/pkg/config/config.go +++ b/extensions/gateway/pkg/config/config.go @@ -4,42 +4,43 @@ import "github.com/owncloud/ocis/ocis-pkg/shared" type Config struct { *shared.Commons `yaml:"-"` - Service Service `yaml:"-"` - Tracing *Tracing `yaml:"tracing"` - Logging *Logging `yaml:"log"` - Debug Debug `yaml:"debug"` - Supervised bool + + Service Service `yaml:"-"` + Tracing *Tracing `yaml:"tracing"` + Logging *Logging `yaml:"log"` + Debug Debug `yaml:"debug"` + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + SkipUserGroupsInToken bool - CommitShareToStorageGrant bool - CommitShareToStorageRef bool - ShareFolder string - DisableHomeCreationOnLogin bool - TransferSecret string `env:"STORAGE_TRANSFER_SECRET"` - TransferExpires int - HomeMapping string - EtagCacheTTL int + CommitShareToStorageGrant bool `yaml:"commit_share_to_storage_grant"` + CommitShareToStorageRef bool `yaml:"commit_share_to_storage_ref"` + ShareFolder string `yaml:"share_folder"` + DisableHomeCreationOnLogin bool `yaml:"disable_home_creation_on_login"` + TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"` + TransferExpires int `yaml:"transfer_expires"` + HomeMapping string `yaml:"home_mapping"` + EtagCacheTTL int `yaml:"etag_cache_ttl"` - UsersEndpoint string - GroupsEndpoint string - PermissionsEndpoint string - SharingEndpoint string - DataGatewayPublicURL string - FrontendPublicURL string `env:"OCIS_URL;GATEWAY_FRONTEND_PUBLIC_URL"` - AuthBasicEndpoint string - AuthBearerEndpoint string - AuthMachineEndpoint string - StoragePublicLinkEndpoint string - StorageUsersEndpoint string - StorageSharesEndpoint string + UsersEndpoint string `yaml:"users_endpoint"` + GroupsEndpoint string `yaml:"groups_endpoint"` + PermissionsEndpoint string `yaml:"permissions_endpoint"` + SharingEndpoint string `yaml:"sharing_endpoint"` + FrontendPublicURL string `yaml:"frontend_public_url" env:"OCIS_URL;GATEWAY_FRONTEND_PUBLIC_URL"` + AuthBasicEndpoint string `yaml:"auth_basic_endpoint"` + AuthBearerEndpoint string `yaml:"auth_bearer_endpoint"` + AuthMachineEndpoint string `yaml:"auth_machine_endpoint"` + StoragePublicLinkEndpoint string `yaml:"storage_public_link_endpoint"` + StorageUsersEndpoint string `yaml:"storage_users_endpoint"` + StorageSharesEndpoint string `yaml:"storage_shares_endpoint"` - StorageRegistry StorageRegistry - AppRegistry AppRegistry + StorageRegistry StorageRegistry `yaml:"storage_registry"` + AppRegistry AppRegistry `yaml:"app_registry"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;GATEWAY_TRACING_ENABLED" desc:"Activates tracing."` diff --git a/extensions/gateway/pkg/config/defaults/defaultconfig.go b/extensions/gateway/pkg/config/defaults/defaultconfig.go index 44c3dc0df3..21e3cc1862 100644 --- a/extensions/gateway/pkg/config/defaults/defaultconfig.go +++ b/extensions/gateway/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -27,14 +26,14 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "gateway", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, CommitShareToStorageGrant: true, CommitShareToStorageRef: true, ShareFolder: "Shares", DisableHomeCreationOnLogin: true, - TransferSecret: "replace-me-with-a-transfer-secret", TransferExpires: 24 * 60 * 60, HomeMapping: "", EtagCacheTTL: 0, @@ -43,7 +42,6 @@ func DefaultConfig() *config.Config { GroupsEndpoint: "localhost:9160", PermissionsEndpoint: "localhost:9191", SharingEndpoint: "localhost:9150", - DataGatewayPublicURL: "", FrontendPublicURL: "https://localhost:9200", AuthBasicEndpoint: "localhost:9146", AuthBearerEndpoint: "localhost:9148", @@ -85,6 +83,26 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.TransferSecret == "" && cfg.Commons != nil && cfg.Commons.TransferSecret != "" { + cfg.TransferSecret = cfg.Commons.TransferSecret + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/gateway/pkg/config/parser/parse.go b/extensions/gateway/pkg/config/parser/parse.go new file mode 100644 index 0000000000..424efdbfb2 --- /dev/null +++ b/extensions/gateway/pkg/config/parser/parse.go @@ -0,0 +1,46 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/gateway/pkg/config" + "github.com/owncloud/ocis/extensions/gateway/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.TransferSecret == "" { + return shared.MissingRevaTransferSecretError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/gateway/pkg/config/reva.go b/extensions/gateway/pkg/config/reva.go new file mode 100644 index 0000000000..2a5534c7e2 --- /dev/null +++ b/extensions/gateway/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;GATEWAY_JWT_SECRET"` +} diff --git a/extensions/glauth/pkg/command/health.go b/extensions/glauth/pkg/command/health.go index c6e54893ce..0ec6170921 100644 --- a/extensions/glauth/pkg/command/health.go +++ b/extensions/glauth/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/glauth/pkg/command/server.go b/extensions/glauth/pkg/command/server.go index fda86d30c1..5a674cdc94 100644 --- a/extensions/glauth/pkg/command/server.go +++ b/extensions/glauth/pkg/command/server.go @@ -28,7 +28,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/glauth/pkg/config/defaults/defaultconfig.go b/extensions/glauth/pkg/config/defaults/defaultconfig.go index 8d0eb366da..d4508ee9d7 100644 --- a/extensions/glauth/pkg/config/defaults/defaultconfig.go +++ b/extensions/glauth/pkg/config/defaults/defaultconfig.go @@ -9,10 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/glauth/pkg/config/parser/parse.go b/extensions/glauth/pkg/config/parser/parse.go index 532fb51495..a3598df4bc 100644 --- a/extensions/glauth/pkg/config/parser/parse.go +++ b/extensions/glauth/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -28,5 +28,10 @@ func ParseConfig(cfg *config.Config) error { // sanitize config defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/extensions/graph-explorer/pkg/command/health.go b/extensions/graph-explorer/pkg/command/health.go index a6122e5af7..8ee126ebb2 100644 --- a/extensions/graph-explorer/pkg/command/health.go +++ b/extensions/graph-explorer/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/graph-explorer/pkg/command/server.go b/extensions/graph-explorer/pkg/command/server.go index 093cbe60b3..562cfa569c 100644 --- a/extensions/graph-explorer/pkg/command/server.go +++ b/extensions/graph-explorer/pkg/command/server.go @@ -23,7 +23,11 @@ func Server(cfg *config.Config) *cli.Command { Usage: fmt.Sprintf("start %s extension without runtime (unsupervised mode)", cfg.Service.Name), Category: "server", Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/graph-explorer/pkg/config/defaults/defaultconfig.go b/extensions/graph-explorer/pkg/config/defaults/defaultconfig.go index a343da50af..27b194940a 100644 --- a/extensions/graph-explorer/pkg/config/defaults/defaultconfig.go +++ b/extensions/graph-explorer/pkg/config/defaults/defaultconfig.go @@ -8,10 +8,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/graph-explorer/pkg/config/parser/parse.go b/extensions/graph-explorer/pkg/config/parser/parse.go index 499fbb8f36..ae369113fc 100644 --- a/extensions/graph-explorer/pkg/config/parser/parse.go +++ b/extensions/graph-explorer/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -30,5 +30,9 @@ func ParseConfig(cfg *config.Config) error { // sanitize config defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/extensions/graph/pkg/command/health.go b/extensions/graph/pkg/command/health.go index 0de5812985..befa8a2e5c 100644 --- a/extensions/graph/pkg/command/health.go +++ b/extensions/graph/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/graph/pkg/command/server.go b/extensions/graph/pkg/command/server.go index c7e3e317a3..1a281fc895 100644 --- a/extensions/graph/pkg/command/server.go +++ b/extensions/graph/pkg/command/server.go @@ -23,7 +23,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/graph/pkg/config/config.go b/extensions/graph/pkg/config/config.go index 4d11d73f93..d147eaa30c 100644 --- a/extensions/graph/pkg/config/config.go +++ b/extensions/graph/pkg/config/config.go @@ -18,8 +18,8 @@ type Config struct { HTTP HTTP `yaml:"http"` - Reva Reva `yaml:"reva"` - TokenManager TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + TokenManager *TokenManager `yaml:"token_manager"` Spaces Spaces `yaml:"spaces"` Identity Identity `yaml:"identity"` diff --git a/extensions/graph/pkg/config/defaults/defaultconfig.go b/extensions/graph/pkg/config/defaults/defaultconfig.go index 512fa68d10..a9a50720df 100644 --- a/extensions/graph/pkg/config/defaults/defaultconfig.go +++ b/extensions/graph/pkg/config/defaults/defaultconfig.go @@ -6,6 +6,13 @@ import ( "github.com/owncloud/ocis/extensions/graph/pkg/config" ) +func FullDefaultConfig() *config.Config { + cfg := DefaultConfig() + EnsureDefaults(cfg) + Sanitize(cfg) + return cfg +} + func DefaultConfig() *config.Config { return &config.Config{ Debug: config.Debug{ @@ -20,12 +27,9 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "graph", }, - Reva: config.Reva{ + 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/", @@ -38,7 +42,6 @@ func DefaultConfig() *config.Config { URI: "ldaps://localhost:9235", Insecure: true, BindDN: "uid=libregraph,ou=sysusers,o=libregraph-idm", - BindPassword: "idm", UseServerUUID: false, WriteEnabled: true, UserBaseDN: "ou=users,o=libregraph-idm", @@ -89,6 +92,14 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/graph/pkg/config/parser/parse.go b/extensions/graph/pkg/config/parser/parse.go index cf4612cc88..f554a623d8 100644 --- a/extensions/graph/pkg/config/parser/parse.go +++ b/extensions/graph/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/graph/pkg/config" "github.com/owncloud/ocis/extensions/graph/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +30,17 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.Identity.Backend == "ldap" && cfg.Identity.LDAP.BindPassword == "" { + return shared.MissingLDAPBindPassword(cfg.Service.Name) + } + return nil } diff --git a/extensions/graph/pkg/service/v0/drives.go b/extensions/graph/pkg/service/v0/drives.go index 673f246fa5..821e664898 100644 --- a/extensions/graph/pkg/service/v0/drives.go +++ b/extensions/graph/pkg/service/v0/drives.go @@ -31,8 +31,19 @@ import ( merrors "go-micro.dev/v4/errors" ) -// GetDrives implements the Service interface. +// GetDrives lists all drives the current user has access to func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { + g.getDrives(w, r, false) +} + +// GetAllDrives lists all drives, including other user's drives, if the current +// user has the permission. +func (g Graph) GetAllDrives(w http.ResponseWriter, r *http.Request) { + g.getDrives(w, r, true) +} + +// getDrives implements the Service interface. +func (g Graph) getDrives(w http.ResponseWriter, r *http.Request, unrestricted bool) { sanitizedPath := strings.TrimPrefix(r.URL.Path, "/graph/v1.0/") // Parse the request with odata parser odataReq, err := godata.ParseRequest(r.Context(), sanitizedPath, r.URL.Query()) @@ -41,7 +52,10 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, err.Error()) return } - g.logger.Info().Interface("query", r.URL.Query()).Msg("Calling GetDrives") + g.logger.Debug(). + Interface("query", r.URL.Query()). + Bool("unrestricted", unrestricted). + Msg("Calling getDrives") ctx := r.Context() filters, err := generateCs3Filters(odataReq) @@ -50,7 +64,7 @@ func (g Graph) GetDrives(w http.ResponseWriter, r *http.Request) { errorcode.NotSupported.Render(w, r, http.StatusNotImplemented, err.Error()) return } - res, err := g.ListStorageSpacesWithFilters(ctx, filters) + res, err := g.ListStorageSpacesWithFilters(ctx, filters, unrestricted) switch { case err != nil: g.logger.Error().Err(err).Msg(ListStorageSpacesTransportErr) @@ -106,7 +120,7 @@ func (g Graph) GetSingleDrive(w http.ResponseWriter, r *http.Request) { ctx := r.Context() filters := []*storageprovider.ListStorageSpacesRequest_Filter{listStorageSpacesIDFilter(driveID)} - res, err := g.ListStorageSpacesWithFilters(ctx, filters) + res, err := g.ListStorageSpacesWithFilters(ctx, filters, true) switch { case err != nil: g.logger.Error().Err(err).Msg(ListStorageSpacesTransportErr) @@ -273,7 +287,8 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) { identifierParts := strings.Split(driveID, "!") switch len(identifierParts) { case 1: - root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[0] + sID, _ := resourceid.StorageIDUnwrap(identifierParts[0]) + root.StorageId, root.OpaqueId = identifierParts[0], sID case 2: root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[1] default: @@ -398,7 +413,7 @@ func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, storageSpaces } // ListStorageSpacesWithFilters List Storage Spaces using filters -func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*storageprovider.ListStorageSpacesRequest_Filter) (*storageprovider.ListStorageSpacesResponse, error) { +func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*storageprovider.ListStorageSpacesRequest_Filter, unrestricted bool) (*storageprovider.ListStorageSpacesResponse, error) { client := g.GetGatewayClient() permissions := make(map[string]struct{}, 1) @@ -423,17 +438,35 @@ func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*stor Decoder: "json", Value: value, }, + "unrestricted": { + Decoder: "plain", + Value: []byte(strconv.FormatBool(unrestricted)), + }, }}, Filters: filters, }) return res, err } +func generateSpaceId(id *storageprovider.ResourceId) (spaceID string) { + spaceID = id.GetStorageId() + // 2nd ID to compare is the opaque ID of the Space Root + spaceID2 := id.GetOpaqueId() + if strings.Contains(spaceID, "$") { + spaceID2, _ = resourceid.StorageIDUnwrap(spaceID) + } + // Append opaqueID only if it is different from the spaceID2 + if id.OpaqueId != spaceID2 { + spaceID += "!" + id.OpaqueId + } + return spaceID +} + func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, space *storageprovider.StorageSpace) (*libregraph.Drive, error) { if space.Root == nil { return nil, fmt.Errorf("space has no root") } - rootID := resourceid.OwnCloudResourceIDWrap(space.Root) + spaceID := generateSpaceId(space.Root) var permissions []libregraph.Permission if space.Opaque != nil { @@ -491,18 +524,14 @@ func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, spa } } - spaceID := space.Root.StorageId - if space.Root.OpaqueId != space.Root.StorageId { - spaceID = rootID - } drive := &libregraph.Drive{ - Id: &spaceID, + Id: libregraph.PtrString(spaceID), Name: &space.Name, //"createdDateTime": "string (timestamp)", // TODO read from StorageSpace ... needs Opaque for now //"description": "string", // TODO read from StorageSpace ... needs Opaque for now DriveType: &space.SpaceType, Root: &libregraph.DriveItem{ - Id: &rootID, + Id: libregraph.PtrString(resourceid.OwnCloudResourceIDWrap(space.Root)), Permissions: permissions, }, } @@ -735,9 +764,10 @@ func (g Graph) DeleteDrive(w http.ResponseWriter, r *http.Request) { root := &storageprovider.ResourceId{} identifierParts := strings.Split(driveID, "!") + sID, _ := resourceid.StorageIDUnwrap(identifierParts[0]) switch len(identifierParts) { case 1: - root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[0] + root.StorageId, root.OpaqueId = identifierParts[0], sID case 2: root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[1] default: diff --git a/extensions/graph/pkg/service/v0/graph_suite_test.go b/extensions/graph/pkg/service/v0/graph_suite_test.go index 1c6cfc6cc9..6b34ae0631 100644 --- a/extensions/graph/pkg/service/v0/graph_suite_test.go +++ b/extensions/graph/pkg/service/v0/graph_suite_test.go @@ -3,7 +3,7 @@ package svc_test import ( "testing" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/extensions/graph/pkg/service/v0/graph_test.go b/extensions/graph/pkg/service/v0/graph_test.go index fe328d93a6..8ad28656ee 100644 --- a/extensions/graph/pkg/service/v0/graph_test.go +++ b/extensions/graph/pkg/service/v0/graph_test.go @@ -13,10 +13,11 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/v2/pkg/rgrpc/status" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" libregraph "github.com/owncloud/libre-graph-api-go" "github.com/owncloud/ocis/extensions/graph/mocks" + "github.com/owncloud/ocis/extensions/graph/pkg/config" "github.com/owncloud/ocis/extensions/graph/pkg/config/defaults" service "github.com/owncloud/ocis/extensions/graph/pkg/service/v0" "github.com/owncloud/ocis/extensions/graph/pkg/service/v0/errorcode" @@ -30,15 +31,19 @@ var _ = Describe("Graph", func() { httpClient *mocks.HTTPClient eventsPublisher mocks.Publisher ctx context.Context + cfg *config.Config ) JustBeforeEach(func() { ctx = context.Background() + cfg = defaults.FullDefaultConfig() + cfg.TokenManager.JWTSecret = "loremipsum" + gatewayClient = &mocks.GatewayClient{} httpClient = &mocks.HTTPClient{} eventsPublisher = mocks.Publisher{} svc = service.NewService( - service.Config(defaults.DefaultConfig()), + service.Config(cfg), service.WithGatewayClient(gatewayClient), service.WithHTTPClient(httpClient), service.EventsPublisher(&eventsPublisher), @@ -196,7 +201,7 @@ var _ = Describe("Graph", func() { Id: &provider.StorageSpaceId{OpaqueId: "aID!differentID"}, SpaceType: "mountpoint", Root: &provider.ResourceId{ - StorageId: "aID", + StorageId: "prID$aID", OpaqueId: "differentID", }, Name: "New Folder", @@ -241,11 +246,11 @@ var _ = Describe("Graph", func() { value := response["value"][0] Expect(*value.DriveAlias).To(Equal("mountpoint/new-folder")) Expect(*value.DriveType).To(Equal("mountpoint")) - Expect(*value.Id).To(Equal("aID!differentID")) + Expect(*value.Id).To(Equal("prID$aID!differentID")) Expect(*value.Name).To(Equal("New Folder")) - Expect(*value.Root.WebDavUrl).To(Equal("https://localhost:9200/dav/spaces/aID!differentID")) + Expect(*value.Root.WebDavUrl).To(Equal("https://localhost:9200/dav/spaces/prID$aID!differentID")) Expect(*value.Root.ETag).To(Equal("101112131415")) - Expect(*value.Root.Id).To(Equal("aID!differentID")) + Expect(*value.Root.Id).To(Equal("prID$aID!differentID")) Expect(*value.Root.RemoteItem.ETag).To(Equal("123456789")) Expect(*value.Root.RemoteItem.Id).To(Equal("ownerStorageID!opaqueID")) Expect(value.Root.RemoteItem.LastModifiedDateTime.UTC()).To(Equal(time.Unix(1648327606, 0).UTC())) diff --git a/extensions/graph/pkg/service/v0/service.go b/extensions/graph/pkg/service/v0/service.go index 11fe37c2fe..c198834716 100644 --- a/extensions/graph/pkg/service/v0/service.go +++ b/extensions/graph/pkg/service/v0/service.go @@ -59,7 +59,7 @@ func NewService(opts ...Option) Service { switch options.Config.Identity.Backend { case "cs3": backend = &identity.CS3{ - Config: &options.Config.Reva, + Config: options.Config.Reva, Logger: &options.Logger, } case "ldap": @@ -173,7 +173,7 @@ func NewService(opts ...Option) Service { account.JWTSecret(options.Config.TokenManager.JWTSecret)), ) r.Route("/drives", func(r chi.Router) { - r.Get("/", svc.GetDrives) + r.Get("/", svc.GetAllDrives) r.Post("/", svc.CreateDrive) r.Route("/{driveID}", func(r chi.Router) { r.Patch("/", svc.UpdateDrive) diff --git a/extensions/group/pkg/command/command.go b/extensions/group/pkg/command/command.go index 0f2162e0a3..9f5d45dfe6 100644 --- a/extensions/group/pkg/command/command.go +++ b/extensions/group/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" "path/filepath" @@ -11,6 +12,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/group/pkg/config" + "github.com/owncloud/ocis/extensions/group/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/ldap" @@ -26,6 +28,13 @@ func Groups(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "groups", Usage: "start groups service", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -111,8 +120,8 @@ func groupsConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]inter "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/group/pkg/config/config.go b/extensions/group/pkg/config/config.go index c0eb2a4a71..415db0255e 100644 --- a/extensions/group/pkg/config/config.go +++ b/extensions/group/pkg/config/config.go @@ -8,16 +8,17 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool - GroupMembersCacheExpiration int - Driver string - Drivers Drivers + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` + GroupMembersCacheExpiration int `yaml:"group_members_cache_expiration"` + Driver string `yaml:"driver"` + Drivers Drivers `yaml:"drivers"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;GROUPS_TRACING_ENABLED" desc:"Activates tracing."` @@ -64,7 +65,7 @@ type LDAPDriver struct { CACert string `env:"LDAP_CACERT;GROUPS_LDAP_CACERT"` Insecure bool `env:"LDAP_INSECURE;GROUPS_LDAP_INSECURE"` BindDN string `env:"LDAP_BIND_DN;GROUPS_LDAP_BIND_DN"` - BindPassword string `env:"LDAP_BIND_PASSWORD;GROUPS_LDAP_BIND_PASSWORD"` + BindPassword string `yaml:"bind_password" env:"LDAP_BIND_PASSWORD;GROUPS_LDAP_BIND_PASSWORD"` UserBaseDN string `env:"LDAP_USER_BASE_DN;GROUPS_LDAP_USER_BASE_DN"` GroupBaseDN string `env:"LDAP_GROUP_BASE_DN;GROUPS_LDAP_GROUP_BASE_DN"` UserScope string `env:"LDAP_USER_SCOPE;GROUPS_LDAP_USER_SCOPE"` diff --git a/extensions/group/pkg/config/defaults/defaultconfig.go b/extensions/group/pkg/config/defaults/defaultconfig.go index 372bcc6952..47c10b9f79 100644 --- a/extensions/group/pkg/config/defaults/defaultconfig.go +++ b/extensions/group/pkg/config/defaults/defaultconfig.go @@ -9,9 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -28,12 +27,13 @@ func DefaultConfig() *config.Config { Protocol: "tcp", }, Service: config.Service{ - Name: "user", + Name: "group", }, GroupMembersCacheExpiration: 5, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - Driver: "ldap", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + Driver: "ldap", Drivers: config.Drivers{ LDAP: config.LDAPDriver{ URI: "ldaps://localhost:9235", @@ -49,7 +49,6 @@ func DefaultConfig() *config.Config { UserObjectClass: "inetOrgPerson", GroupObjectClass: "groupOfNames", BindDN: "uid=reva,ou=sysusers,o=libregraph-idm", - BindPassword: "reva", IDP: "https://localhost:9200", UserSchema: config.LDAPUserSchema{ ID: "ownclouduuid", @@ -108,6 +107,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/group/pkg/config/parser/parse.go b/extensions/group/pkg/config/parser/parse.go new file mode 100644 index 0000000000..f1e7880c9b --- /dev/null +++ b/extensions/group/pkg/config/parser/parse.go @@ -0,0 +1,46 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/group/pkg/config" + "github.com/owncloud/ocis/extensions/group/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.Drivers.LDAP.BindPassword == "" && cfg.Driver == "ldap" { + return shared.MissingLDAPBindPassword(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/group/pkg/config/reva.go b/extensions/group/pkg/config/reva.go new file mode 100644 index 0000000000..e2aae1a7a0 --- /dev/null +++ b/extensions/group/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;GROUPS_JWT_SECRET"` +} diff --git a/extensions/idm/ldif/base.ldif.tmpl b/extensions/idm/ldif/base.ldif.tmpl index 1cbaaec4c2..e29221c62f 100644 --- a/extensions/idm/ldif/base.ldif.tmpl +++ b/extensions/idm/ldif/base.ldif.tmpl @@ -40,17 +40,4 @@ userPassword:: {{ .Password }} {{ end -}} -## Service user for the settings service -dn: uid=95cb8724-03b2-11eb-a0a6-c33ef8ef53ad,ou=users,o=libregraph-idm -objectClass: inetOrgPerson -objectClass: organizationalPerson -objectClass: ownCloud -objectClass: person -objectClass: top -uid: 95cb8724-03b2-11eb-a0a6-c33ef8ef53ad -givenName: 95cb8724-03b2-11eb-a0a6-c33ef8ef53ad -sn: 95cb8724-03b2-11eb-a0a6-c33ef8ef53ad -cn: 95cb8724-03b2-11eb-a0a6-c33ef8ef53ad -displayName: 95cb8724-03b2-11eb-a0a6-c33ef8ef53ad -ownCloudUUID: 95cb8724-03b2-11eb-a0a6-c33ef8ef53ad diff --git a/extensions/idm/pkg/command/health.go b/extensions/idm/pkg/command/health.go index cc61b7c1dc..22bae6b94f 100644 --- a/extensions/idm/pkg/command/health.go +++ b/extensions/idm/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/idm/pkg/command/server.go b/extensions/idm/pkg/command/server.go index c63b0f2af7..90f399dfa9 100644 --- a/extensions/idm/pkg/command/server.go +++ b/extensions/idm/pkg/command/server.go @@ -29,7 +29,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/idm/pkg/config/defaults/defaultconfig.go b/extensions/idm/pkg/config/defaults/defaultconfig.go index 983db3c071..25ea4785fe 100644 --- a/extensions/idm/pkg/config/defaults/defaultconfig.go +++ b/extensions/idm/pkg/config/defaults/defaultconfig.go @@ -9,10 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -22,12 +20,6 @@ func DefaultConfig() *config.Config { Name: "idm", }, CreateDemoUsers: false, - ServiceUserPasswords: config.ServiceUserPasswords{ - OcisAdmin: "admin", - Idm: "idm", - Idp: "idp", - Reva: "reva", - }, IDM: config.Settings{ LDAPSAddr: "127.0.0.1:9235", Cert: path.Join(defaults.BaseDataPath(), "idm", "ldap.crt"), diff --git a/extensions/idm/pkg/config/parser/parse.go b/extensions/idm/pkg/config/parser/parse.go index 0998543ad0..7d04c55ad4 100644 --- a/extensions/idm/pkg/config/parser/parse.go +++ b/extensions/idm/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/idm/pkg/config" "github.com/owncloud/ocis/extensions/idm/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -28,5 +29,24 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.ServiceUserPasswords.Idm == "" { + return shared.MissingServiceUserPassword(cfg.Service.Name, "IDM") + } + + if cfg.ServiceUserPasswords.OcisAdmin == "" { + return shared.MissingServiceUserPassword(cfg.Service.Name, "admin") + } + + if cfg.ServiceUserPasswords.Idp == "" { + return shared.MissingServiceUserPassword(cfg.Service.Name, "IDP") + } + if cfg.ServiceUserPasswords.Reva == "" { + return shared.MissingServiceUserPassword(cfg.Service.Name, "REVA") + } + return nil } diff --git a/extensions/idp/pkg/command/health.go b/extensions/idp/pkg/command/health.go index cd282e8bac..3ff2833bb2 100644 --- a/extensions/idp/pkg/command/health.go +++ b/extensions/idp/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/idp/pkg/command/server.go b/extensions/idp/pkg/command/server.go index c541245d01..8b3f25e300 100644 --- a/extensions/idp/pkg/command/server.go +++ b/extensions/idp/pkg/command/server.go @@ -23,7 +23,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/idp/pkg/config/defaults/defaultconfig.go b/extensions/idp/pkg/config/defaults/defaultconfig.go index d9b68fb506..b3498b9755 100644 --- a/extensions/idp/pkg/config/defaults/defaultconfig.go +++ b/extensions/idp/pkg/config/defaults/defaultconfig.go @@ -10,10 +10,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -71,7 +69,6 @@ func DefaultConfig() *config.Config { URI: "ldaps://localhost:9235", TLSCACert: path.Join(defaults.BaseDataPath(), "idm", "ldap.crt"), BindDN: "uid=idp,ou=sysusers,o=libregraph-idm", - BindPassword: "idp", BaseDN: "ou=users,o=libregraph-idm", Scope: "sub", LoginAttribute: "uid", diff --git a/extensions/idp/pkg/config/parser/parse.go b/extensions/idp/pkg/config/parser/parse.go index 101ea85bdc..b75b10b398 100644 --- a/extensions/idp/pkg/config/parser/parse.go +++ b/extensions/idp/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/idp/pkg/config" "github.com/owncloud/ocis/extensions/idp/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +30,13 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.Ldap.BindPassword == "" { + return shared.MissingLDAPBindPassword(cfg.Service.Name) + } + return nil } diff --git a/extensions/nats/pkg/command/server.go b/extensions/nats/pkg/command/server.go index 79f3f7f443..14234b4243 100644 --- a/extensions/nats/pkg/command/server.go +++ b/extensions/nats/pkg/command/server.go @@ -20,7 +20,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/nats/pkg/config/defaults/defaultconfig.go b/extensions/nats/pkg/config/defaults/defaultconfig.go index f9435ff4df..a522ca6785 100644 --- a/extensions/nats/pkg/config/defaults/defaultconfig.go +++ b/extensions/nats/pkg/config/defaults/defaultconfig.go @@ -12,10 +12,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/nats/pkg/config/parser/parse.go b/extensions/nats/pkg/config/parser/parse.go index 2a427a3bd9..a3a27113e2 100644 --- a/extensions/nats/pkg/config/parser/parse.go +++ b/extensions/nats/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +29,9 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/extensions/notifications/pkg/channels/channels.go b/extensions/notifications/pkg/channels/channels.go index 2d6d9203ec..956ee692df 100644 --- a/extensions/notifications/pkg/channels/channels.go +++ b/extensions/notifications/pkg/channels/channels.go @@ -86,7 +86,7 @@ func (m Mail) getReceiverAddresses(receivers []string) ([]string, error) { res, err := m.gatewayClient.Authenticate(context.Background(), &gateway.AuthenticateRequest{ Type: "machine", ClientId: "userid:" + id, - ClientSecret: m.conf.Notifications.MachineAuthSecret, + ClientSecret: m.conf.Notifications.MachineAuthAPIKey, }) if err != nil { return nil, err diff --git a/extensions/notifications/pkg/command/root.go b/extensions/notifications/pkg/command/root.go index 7a38a24d4f..e2534e15a6 100644 --- a/extensions/notifications/pkg/command/root.go +++ b/extensions/notifications/pkg/command/root.go @@ -48,7 +48,7 @@ type SutureService struct { // NewSutureService creates a new notifications.SutureService func NewSutureService(cfg *ociscfg.Config) suture.Service { - cfg.Settings.Commons = cfg.Commons + cfg.Notifications.Commons = cfg.Commons return SutureService{ cfg: cfg.Notifications, } diff --git a/extensions/notifications/pkg/command/server.go b/extensions/notifications/pkg/command/server.go index 4a887fc4b9..a51fda7010 100644 --- a/extensions/notifications/pkg/command/server.go +++ b/extensions/notifications/pkg/command/server.go @@ -21,7 +21,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/notifications/pkg/config/config.go b/extensions/notifications/pkg/config/config.go index 7cc1838523..36ff2e6c8c 100644 --- a/extensions/notifications/pkg/config/config.go +++ b/extensions/notifications/pkg/config/config.go @@ -22,10 +22,11 @@ type Config struct { // Notifications definces the config options for the notifications service. type Notifications struct { + *shared.Commons `yaml:"-"` SMTP SMTP `yaml:"SMTP"` Events Events `yaml:"events"` RevaGateway string `yaml:"reva_gateway" env:"REVA_GATEWAY;NOTIFICATIONS_REVA_GATEWAY"` - MachineAuthSecret string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;NOTIFICATIONS_MACHINE_AUTH_API_KEY"` + MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY;NOTIFICATIONS_MACHINE_AUTH_API_KEY"` } // SMTP combines the smtp configuration options. diff --git a/extensions/notifications/pkg/config/defaults/defaultconfig.go b/extensions/notifications/pkg/config/defaults/defaultconfig.go index 19c3cc2df8..09d08d13fb 100644 --- a/extensions/notifications/pkg/config/defaults/defaultconfig.go +++ b/extensions/notifications/pkg/config/defaults/defaultconfig.go @@ -1,13 +1,13 @@ package defaults -import "github.com/owncloud/ocis/extensions/notifications/pkg/config" +import ( + "github.com/owncloud/ocis/extensions/notifications/pkg/config" +) func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -31,8 +31,7 @@ func DefaultConfig() *config.Config { Cluster: "ocis-cluster", ConsumerGroup: "notifications", }, - RevaGateway: "127.0.0.1:9142", - MachineAuthSecret: "change-me-please", + RevaGateway: "127.0.0.1:9142", }, } } @@ -49,6 +48,10 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Log == nil { cfg.Log = &config.Log{} } + + if cfg.Notifications.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.Notifications.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/notifications/pkg/config/parser/parse.go b/extensions/notifications/pkg/config/parser/parse.go index 2a4876a33c..85ac780a34 100644 --- a/extensions/notifications/pkg/config/parser/parse.go +++ b/extensions/notifications/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/notifications/pkg/config" "github.com/owncloud/ocis/extensions/notifications/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +30,13 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.Notifications.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + return nil } diff --git a/extensions/ocdav/pkg/command/ocdav.go b/extensions/ocdav/pkg/command/ocdav.go index e73f5d1b1e..20bb8a29b6 100644 --- a/extensions/ocdav/pkg/command/ocdav.go +++ b/extensions/ocdav/pkg/command/ocdav.go @@ -4,14 +4,13 @@ import ( "context" "flag" "fmt" - "strings" "github.com/cs3org/reva/v2/pkg/micro/ocdav" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/ocdav/pkg/config" + "github.com/owncloud/ocis/extensions/ocdav/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" - "github.com/owncloud/ocis/ocis-pkg/conversions" "github.com/owncloud/ocis/ocis-pkg/log" "github.com/owncloud/ocis/ocis-pkg/sync" "github.com/owncloud/ocis/ocis-pkg/tracing" @@ -25,11 +24,12 @@ func OCDav(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "ocdav", Usage: "start ocdav service", - Before: func(c *cli.Context) error { - if err := loadUserAgent(c, cfg); err != nil { - return err + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) } - return nil + return err }, Action: func(c *cli.Context) error { logCfg := cfg.Logging @@ -59,8 +59,8 @@ func OCDav(cfg *config.Config) *cli.Command { ocdav.Insecure(cfg.Insecure), ocdav.PublicURL(cfg.PublicURL), ocdav.Prefix(cfg.HTTP.Prefix), - ocdav.GatewaySvc(cfg.GatewayEndpoint), - ocdav.JWTSecret(cfg.JWTSecret), + ocdav.GatewaySvc(cfg.Reva.Address), + ocdav.JWTSecret(cfg.TokenManager.JWTSecret), // ocdav.FavoriteManager() // FIXME needs a proper persistence implementation // ocdav.LockSystem(), // will default to the CS3 lock system // ocdav.TLSConfig() // tls config for the http server @@ -144,28 +144,3 @@ func (s OCDavSutureService) Serve(ctx context.Context) error { return nil } - -// loadUserAgent reads the user-agent-whitelist-lock-in, since it is a string flag, and attempts to construct a map of -// "user-agent":"challenge" locks in for Reva. -// Modifies cfg. Spaces don't need to be trimmed as urfavecli takes care of it. User agents with spaces are valid. i.e: -// Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:83.0) Gecko/20100101 Firefox/83.0 -// This function works by relying in our format of specifying [user-agent:challenge] and the fact that the user agent -// might contain ":" (colon), so the original string is reversed, split in two parts, by the time it is split we -// have the indexes reversed and the tuple is in the format of [challenge:user-agent], then the same process is applied -// in reverse for each individual part -func loadUserAgent(c *cli.Context, cfg *config.Config) error { - cfg.Middleware.Auth.CredentialsByUserAgent = make(map[string]string) - locks := c.StringSlice("user-agent-whitelist-lock-in") - - for _, v := range locks { - vv := conversions.Reverse(v) - parts := strings.SplitN(vv, ":", 2) - if len(parts) != 2 { - return fmt.Errorf("unexpected config value for user-agent lock-in: %v, expected format is user-agent:challenge", v) - } - - cfg.Middleware.Auth.CredentialsByUserAgent[conversions.Reverse(parts[1])] = conversions.Reverse(parts[0]) - } - - return nil -} diff --git a/extensions/ocdav/pkg/config/config.go b/extensions/ocdav/pkg/config/config.go index e81e6b6288..da510a3eff 100644 --- a/extensions/ocdav/pkg/config/config.go +++ b/extensions/ocdav/pkg/config/config.go @@ -8,14 +8,14 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` HTTP HTTPConfig `yaml:"http"` - // JWTSecret used to verify reva access token - JWTSecret string `yaml:"jwt_secret"` - GatewayEndpoint string - SkipUserGroupsInToken bool + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` WebdavNamespace string `yaml:"webdav_namespace"` FilesNamespace string `yaml:"files_namespace"` @@ -26,8 +26,8 @@ type Config struct { // Insecure certificates allowed when making requests to the gateway Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;OCDAV_INSECURE"` // Timeout in seconds when making requests to the gateway - Timeout int64 `yaml:"timeout"` - Middleware Middleware + Timeout int64 `yaml:"timeout"` + Middleware Middleware `yaml:"middleware"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;OCDAV_TRACING_ENABLED" desc:"Activates tracing."` diff --git a/extensions/ocdav/pkg/config/defaults/defaultconfig.go b/extensions/ocdav/pkg/config/defaults/defaultconfig.go index eaffe1c8c5..b55f9e6513 100644 --- a/extensions/ocdav/pkg/config/defaults/defaultconfig.go +++ b/extensions/ocdav/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -28,8 +27,9 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "ocdav", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, WebdavNamespace: "/users/{{.Id.OpaqueId}}", FilesNamespace: "/users/{{.Id.OpaqueId}}", SharesNamespace: "/Shares", @@ -67,6 +67,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/ocdav/pkg/config/parser/parse.go b/extensions/ocdav/pkg/config/parser/parse.go new file mode 100644 index 0000000000..77766296bf --- /dev/null +++ b/extensions/ocdav/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/ocdav/pkg/config" + "github.com/owncloud/ocis/extensions/ocdav/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/ocdav/pkg/config/reva.go b/extensions/ocdav/pkg/config/reva.go new file mode 100644 index 0000000000..4a0f1449be --- /dev/null +++ b/extensions/ocdav/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;OCDAV_JWT_SECRET"` +} diff --git a/extensions/ocs/pkg/command/health.go b/extensions/ocs/pkg/command/health.go index 515f384080..6e7d9c08b1 100644 --- a/extensions/ocs/pkg/command/health.go +++ b/extensions/ocs/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/ocs/pkg/command/server.go b/extensions/ocs/pkg/command/server.go index 0b88c99728..5df57b6103 100644 --- a/extensions/ocs/pkg/command/server.go +++ b/extensions/ocs/pkg/command/server.go @@ -24,7 +24,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/ocs/pkg/config/config.go b/extensions/ocs/pkg/config/config.go index 52d7e95424..b5e7fbe859 100644 --- a/extensions/ocs/pkg/config/config.go +++ b/extensions/ocs/pkg/config/config.go @@ -18,8 +18,8 @@ type Config struct { HTTP HTTP `yaml:"http"` - TokenManager TokenManager `yaml:"token_manager"` - Reva Reva `yaml:"reva"` + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` IdentityManagement IdentityManagement `yaml:"identity_management"` diff --git a/extensions/ocs/pkg/config/defaults/defaultconfig.go b/extensions/ocs/pkg/config/defaults/defaultconfig.go index 6038e0c8d5..20a3e3ca9e 100644 --- a/extensions/ocs/pkg/config/defaults/defaultconfig.go +++ b/extensions/ocs/pkg/config/defaults/defaultconfig.go @@ -8,10 +8,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -37,16 +35,11 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "ocs", }, - - TokenManager: config.TokenManager{ - JWTSecret: "Pive-Fumkiu4", - }, AccountBackend: "cs3", - Reva: config.Reva{ + Reva: &config.Reva{ Address: "127.0.0.1:9142", }, StorageUsersDriver: "ocis", - MachineAuthAPIKey: "change-me-please", IdentityManagement: config.IdentityManagement{ Address: "https://localhost:9200", }, @@ -77,6 +70,25 @@ func EnsureDefaults(cfg *config.Config) { cfg.Tracing = &config.Tracing{} } + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/ocs/pkg/config/parser/parse.go b/extensions/ocs/pkg/config/parser/parse.go index b9c312ca3d..536ed52de1 100644 --- a/extensions/ocs/pkg/config/parser/parse.go +++ b/extensions/ocs/pkg/config/parser/parse.go @@ -5,12 +5,14 @@ import ( "github.com/owncloud/ocis/extensions/ocs/pkg/config" "github.com/owncloud/ocis/extensions/ocs/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +31,17 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + return nil } diff --git a/extensions/ocs/pkg/server/http/svc_test.go b/extensions/ocs/pkg/server/http/svc_test.go index 3c30212a83..a6f4051d4e 100644 --- a/extensions/ocs/pkg/server/http/svc_test.go +++ b/extensions/ocs/pkg/server/http/svc_test.go @@ -723,7 +723,8 @@ func getService() svc.Service { Root: "/", Addr: "localhost:9110", }, - TokenManager: config.TokenManager{ + Reva: &config.Reva{}, + TokenManager: &config.TokenManager{ JWTSecret: jwtSecret, }, Log: &config.Log{ diff --git a/extensions/proxy/pkg/command/health.go b/extensions/proxy/pkg/command/health.go index e3014e5870..a90cb78b41 100644 --- a/extensions/proxy/pkg/command/health.go +++ b/extensions/proxy/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/proxy/pkg/command/server.go b/extensions/proxy/pkg/command/server.go index 8332246399..ed1752ebb7 100644 --- a/extensions/proxy/pkg/command/server.go +++ b/extensions/proxy/pkg/command/server.go @@ -43,7 +43,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) @@ -212,7 +216,7 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config) middleware.AccountResolver( middleware.Logger(logger), middleware.UserProvider(userProvider), - middleware.TokenManagerConfig(cfg.TokenManager), + middleware.TokenManagerConfig(*cfg.TokenManager), middleware.UserOIDCClaim(cfg.UserOIDCClaim), middleware.UserCS3Claim(cfg.UserCS3Claim), middleware.AutoprovisionAccounts(cfg.AutoprovisionAccounts), @@ -227,7 +231,7 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config) // finally, trigger home creation when a user logs in middleware.CreateHome( middleware.Logger(logger), - middleware.TokenManagerConfig(cfg.TokenManager), + middleware.TokenManagerConfig(*cfg.TokenManager), middleware.RevaGatewayClient(revaClient), ), middleware.PublicShareAuth( diff --git a/extensions/proxy/pkg/config/config.go b/extensions/proxy/pkg/config/config.go index 40a8e0d681..f6264f413d 100644 --- a/extensions/proxy/pkg/config/config.go +++ b/extensions/proxy/pkg/config/config.go @@ -18,11 +18,11 @@ type Config struct { HTTP HTTP `yaml:"http"` - Reva Reva `yaml:"reva"` + Reva *Reva `yaml:"reva"` Policies []Policy `yaml:"policies"` OIDC OIDC `yaml:"oidc"` - TokenManager TokenManager `yaml:"token_manager"` + TokenManager *TokenManager `yaml:"token_manager"` PolicySelector *PolicySelector `yaml:"policy_selector"` PreSignedURL PreSignedURL `yaml:"pre_signed_url"` AccountBackend string `yaml:"account_backend" env:"PROXY_ACCOUNT_BACKEND_TYPE"` diff --git a/extensions/proxy/pkg/config/defaults/defaultconfig.go b/extensions/proxy/pkg/config/defaults/defaultconfig.go index e023a005f6..c04ed2e27c 100644 --- a/extensions/proxy/pkg/config/defaults/defaultconfig.go +++ b/extensions/proxy/pkg/config/defaults/defaultconfig.go @@ -8,6 +8,13 @@ import ( "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{ @@ -34,11 +41,8 @@ func DefaultConfig() *config.Config { TTL: 10, }, }, - TokenManager: config.TokenManager{ - JWTSecret: "Pive-Fumkiu4", - }, PolicySelector: nil, - Reva: config.Reva{ + Reva: &config.Reva{ Address: "127.0.0.1:9142", }, PreSignedURL: config.PreSignedURL{ @@ -48,7 +52,6 @@ func DefaultConfig() *config.Config { AccountBackend: "cs3", UserOIDCClaim: "email", UserCS3Claim: "mail", - MachineAuthAPIKey: "change-me-please", AutoprovisionAccounts: false, EnableBasicAuth: false, InsecureBackends: false, @@ -190,6 +193,25 @@ func EnsureDefaults(cfg *config.Config) { cfg.Tracing = &config.Tracing{} } + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/proxy/pkg/config/parser/parse.go b/extensions/proxy/pkg/config/parser/parse.go index 2f29670f65..f792d79557 100644 --- a/extensions/proxy/pkg/config/parser/parse.go +++ b/extensions/proxy/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/proxy/pkg/config" "github.com/owncloud/ocis/extensions/proxy/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -28,5 +29,17 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + return nil } diff --git a/extensions/settings/pkg/command/health.go b/extensions/settings/pkg/command/health.go index 82cc7202f3..620734e00d 100644 --- a/extensions/settings/pkg/command/health.go +++ b/extensions/settings/pkg/command/health.go @@ -16,7 +16,11 @@ func Health(cfg *config.Config) *cli.Command { Name: "health", Usage: "Check health status", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/settings/pkg/command/server.go b/extensions/settings/pkg/command/server.go index 877b48b2fa..407a4f4126 100644 --- a/extensions/settings/pkg/command/server.go +++ b/extensions/settings/pkg/command/server.go @@ -24,7 +24,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/settings/pkg/config/config.go b/extensions/settings/pkg/config/config.go index a60b2df1f3..8182911bf5 100644 --- a/extensions/settings/pkg/config/config.go +++ b/extensions/settings/pkg/config/config.go @@ -23,8 +23,8 @@ type Config struct { DataPath string `yaml:"data_path" env:"SETTINGS_DATA_PATH"` Metadata Metadata `yaml:"metadata_config"` - Asset Asset `yaml:"asset"` - TokenManager TokenManager `yaml:"token_manager"` + Asset Asset `yaml:"asset"` + TokenManager *TokenManager `yaml:"token_manager"` Context context.Context `yaml:"-"` } @@ -40,6 +40,6 @@ type Metadata struct { StorageAddress string `yaml:"storage_addr" env:"STORAGE_GRPC_ADDR"` ServiceUserID string `yaml:"service_user_id" env:"METADATA_SERVICE_USER_UUID"` - ServiceUserIDP string `yaml:"service_user_idp" env:"OCIS_URL;METADATA_SERVICE_USER_IDP"` + ServiceUserIDP string `yaml:"service_user_idp" env:"METADATA_SERVICE_USER_IDP"` MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY"` } diff --git a/extensions/settings/pkg/config/defaults/defaultconfig.go b/extensions/settings/pkg/config/defaults/defaultconfig.go index 4a3a4cd318..5e87d0702b 100644 --- a/extensions/settings/pkg/config/defaults/defaultconfig.go +++ b/extensions/settings/pkg/config/defaults/defaultconfig.go @@ -10,10 +10,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -50,16 +48,11 @@ func DefaultConfig() *config.Config { Asset: config.Asset{ Path: "", }, - TokenManager: config.TokenManager{ - JWTSecret: "Pive-Fumkiu4", - }, Metadata: config.Metadata{ - GatewayAddress: "127.0.0.1:9142", - StorageAddress: "127.0.0.1:9215", - ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - ServiceUserIDP: "https://localhost:9200", - MachineAuthAPIKey: "change-me-please", + GatewayAddress: "127.0.0.1:9215", // metadata storage + StorageAddress: "127.0.0.1:9215", + ServiceUserIDP: "internal", }, } } @@ -87,6 +80,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.Metadata.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.Metadata.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } + + if cfg.Metadata.ServiceUserID == "" && cfg.Commons != nil && cfg.Commons.MetadataUserID != "" { + cfg.Metadata.ServiceUserID = cfg.Commons.MetadataUserID + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/settings/pkg/config/parser/parse.go b/extensions/settings/pkg/config/parser/parse.go index 3880a7ebbc..b59d8ee9fd 100644 --- a/extensions/settings/pkg/config/parser/parse.go +++ b/extensions/settings/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/settings/pkg/config" "github.com/owncloud/ocis/extensions/settings/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -28,5 +29,17 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.Metadata.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + return nil } diff --git a/extensions/settings/pkg/service/v0/settings.go b/extensions/settings/pkg/service/v0/settings.go index abf541a4a9..404845e51c 100644 --- a/extensions/settings/pkg/service/v0/settings.go +++ b/extensions/settings/pkg/service/v0/settings.go @@ -6,9 +6,6 @@ import ( ) const ( - // BundleUUIDRoleMetadata represents the metadata user role - BundleUUIDRoleMetadata = "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad" - // BundleUUIDRoleAdmin represents the admin role BundleUUIDRoleAdmin = "71881883-1768-46bd-a24d-a356a2afdf7f" @@ -532,34 +529,11 @@ func generatePermissionRequests() []*settingssvc.AddSettingToBundleRequest { }, }, }, - { - BundleId: BundleUUIDRoleMetadata, - Setting: &settingsmsg.Setting{ - Id: CreateSpacePermissionID, - Name: CreateSpacePermissionName, - DisplayName: "Create own Space", - Description: "This permission allows to create a space owned by the current user.", - Resource: &settingsmsg.Resource{ - Type: settingsmsg.Resource_TYPE_SYSTEM, // TODO resource type space? self? me? own? - }, - Value: &settingsmsg.Setting_PermissionValue{ - PermissionValue: &settingsmsg.Permission{ - Operation: settingsmsg.Permission_OPERATION_CREATE, - Constraint: settingsmsg.Permission_CONSTRAINT_OWN, - }, - }, - }, - }, } } func defaultRoleAssignments() []*settingsmsg.UserRoleAssignment { return []*settingsmsg.UserRoleAssignment{ - // accounts service user for the metadata user is allowed to create spaces - { - AccountUuid: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - RoleId: BundleUUIDRoleAdmin, - }, // default admin users { AccountUuid: "058bff95-6708-4fe5-91e4-9ea3d377588b", diff --git a/extensions/settings/pkg/store/defaults/defaults.go b/extensions/settings/pkg/store/defaults/defaults.go index b20357257b..27f3d43f9f 100644 --- a/extensions/settings/pkg/store/defaults/defaults.go +++ b/extensions/settings/pkg/store/defaults/defaults.go @@ -17,9 +17,6 @@ const ( // BundleUUIDRoleGuest represents the guest role. BundleUUIDRoleGuest = "38071a68-456a-4553-846a-fa67bf5596cc" - // BundleUUIDRoleMetadata represents the metadata user role - BundleUUIDRoleMetadata = "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad" - // RoleManagementPermissionID is the hardcoded setting UUID for the role management permission RoleManagementPermissionID string = "a53e601e-571f-4f86-8fec-d4576ef49c62" // RoleManagementPermissionName is the hardcoded setting name for the role management permission @@ -68,7 +65,6 @@ func GenerateBundlesDefaultRoles() []*settingsmsg.Bundle { generateBundleUserRole(), generateBundleGuestRole(), generateBundleProfileRequest(), - generateBundleMetadataRole(), generateBundleSpaceAdminRole(), } } @@ -434,36 +430,6 @@ func generateBundleProfileRequest() *settingsmsg.Bundle { } } -func generateBundleMetadataRole() *settingsmsg.Bundle { - return &settingsmsg.Bundle{ - Id: BundleUUIDRoleMetadata, - Name: "metadata", - Type: settingsmsg.Bundle_TYPE_ROLE, - Extension: "ocis-roles", - DisplayName: "Metadata", - Resource: &settingsmsg.Resource{ - Type: settingsmsg.Resource_TYPE_SYSTEM, - }, - Settings: []*settingsmsg.Setting{ - { - Id: CreateSpacePermissionID, - Name: CreateSpacePermissionName, - DisplayName: "Create own Space", - Description: "This permission allows to create a space owned by the current user.", - Resource: &settingsmsg.Resource{ - Type: settingsmsg.Resource_TYPE_SYSTEM, // TODO resource type space? self? me? own? - }, - Value: &settingsmsg.Setting_PermissionValue{ - PermissionValue: &settingsmsg.Permission{ - Operation: settingsmsg.Permission_OPERATION_CREATE, - Constraint: settingsmsg.Permission_CONSTRAINT_OWN, - }, - }, - }, - }, - } -} - // TODO: languageSetting needed? var languageSetting = settingsmsg.Setting_SingleChoiceValue{ SingleChoiceValue: &settingsmsg.SingleChoiceList{ @@ -532,11 +498,6 @@ var languageSetting = settingsmsg.Setting_SingleChoiceValue{ // DefaultRoleAssignments returns (as one might guess) the default role assignments func DefaultRoleAssignments() []*settingsmsg.UserRoleAssignment { return []*settingsmsg.UserRoleAssignment{ - // accounts service user for the metadata user is allowed to create spaces - { - AccountUuid: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - RoleId: BundleUUIDRoleAdmin, - }, // default admin users { AccountUuid: "058bff95-6708-4fe5-91e4-9ea3d377588b", diff --git a/extensions/settings/pkg/store/metadata/assignments.go b/extensions/settings/pkg/store/metadata/assignments.go index 11fafbccb0..88ce7e1c18 100644 --- a/extensions/settings/pkg/store/metadata/assignments.go +++ b/extensions/settings/pkg/store/metadata/assignments.go @@ -13,7 +13,7 @@ import ( // ListRoleAssignments loads and returns all role assignments matching the given assignment identifier. func (s *Store) ListRoleAssignments(accountUUID string) ([]*settingsmsg.UserRoleAssignment, error) { - if s.mdc == nil || accountUUID == "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad" { + if s.mdc == nil { return defaultRoleAssignments(accountUUID), nil } s.Init() diff --git a/extensions/sharing/pkg/command/command.go b/extensions/sharing/pkg/command/command.go index 807b24132b..29cde19357 100644 --- a/extensions/sharing/pkg/command/command.go +++ b/extensions/sharing/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" "path/filepath" @@ -15,6 +16,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/sharing/pkg/config" + "github.com/owncloud/ocis/extensions/sharing/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/thejerf/suture/v4" @@ -26,6 +28,13 @@ func Sharing(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "sharing", Usage: "start sharing service", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -109,8 +118,8 @@ func sharingConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]inte "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ @@ -123,7 +132,7 @@ func sharingConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]inte "drivers": map[string]interface{}{ "json": map[string]interface{}{ "file": cfg.UserSharingDrivers.JSON.File, - "gateway_addr": cfg.GatewayEndpoint, + "gateway_addr": cfg.Reva.Address, }, "sql": map[string]interface{}{ // cernbox sql "db_username": cfg.UserSharingDrivers.SQL.DBUsername, @@ -156,7 +165,7 @@ func sharingConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]inte "drivers": map[string]interface{}{ "json": map[string]interface{}{ "file": cfg.PublicSharingDrivers.JSON.File, - "gateway_addr": cfg.GatewayEndpoint, + "gateway_addr": cfg.Reva.Address, }, "sql": map[string]interface{}{ "db_username": cfg.PublicSharingDrivers.SQL.DBUsername, diff --git a/extensions/sharing/pkg/config/config.go b/extensions/sharing/pkg/config/config.go index 5302b788b7..f81d37faa1 100644 --- a/extensions/sharing/pkg/config/config.go +++ b/extensions/sharing/pkg/config/config.go @@ -8,18 +8,19 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool - UserSharingDriver string - UserSharingDrivers UserSharingDrivers - PublicSharingDriver string - PublicSharingDrivers PublicSharingDrivers - Events Events + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` + UserSharingDriver string `yaml:"user_sharing_driver"` + UserSharingDrivers UserSharingDrivers `yaml:"user_sharin_drivers"` + PublicSharingDriver string `yaml:"public_sharing_driver"` + PublicSharingDrivers PublicSharingDrivers `yaml:"public_sharing_drivers"` + Events Events `yaml:"events"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;SHARING_TRACING_ENABLED" desc:"Activates tracing."` diff --git a/extensions/sharing/pkg/config/defaults/defaultconfig.go b/extensions/sharing/pkg/config/defaults/defaultconfig.go index b7a7f8d991..924e432288 100644 --- a/extensions/sharing/pkg/config/defaults/defaultconfig.go +++ b/extensions/sharing/pkg/config/defaults/defaultconfig.go @@ -9,9 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -30,8 +29,9 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "sharing", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, UserSharingDriver: "json", UserSharingDrivers: config.UserSharingDrivers{ JSON: config.UserSharingJSONDriver{ @@ -48,9 +48,8 @@ func DefaultConfig() *config.Config { JanitorRunInterval: 60, }, CS3: config.UserSharingCS3Driver{ - ProviderAddr: "127.0.0.1:9215", - ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - ServiceUserIDP: "https://localhost:9200", + ProviderAddr: "127.0.0.1:9215", // metadata storage + ServiceUserIDP: "internal", }, }, PublicSharingDriver: "json", @@ -69,9 +68,8 @@ func DefaultConfig() *config.Config { JanitorRunInterval: 60, }, CS3: config.PublicSharingCS3Driver{ - ProviderAddr: "127.0.0.1:9215", - ServiceUserID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - ServiceUserIDP: "https://localhost:9200", + ProviderAddr: "127.0.0.1:9215", // metadata storage + ServiceUserIDP: "internal", }, }, Events: config.Events{ @@ -104,6 +102,38 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.UserSharingDrivers.CS3.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.UserSharingDrivers.CS3.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } + + if cfg.UserSharingDrivers.CS3.ServiceUserID == "" && cfg.Commons != nil && cfg.Commons.MetadataUserID != "" { + cfg.UserSharingDrivers.CS3.ServiceUserID = cfg.Commons.MetadataUserID + } + + if cfg.PublicSharingDrivers.CS3.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.PublicSharingDrivers.CS3.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } + + if cfg.PublicSharingDrivers.CS3.ServiceUserID == "" && cfg.Commons != nil && cfg.Commons.MetadataUserID != "" { + cfg.PublicSharingDrivers.CS3.ServiceUserID = cfg.Commons.MetadataUserID + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/sharing/pkg/config/parser/parse.go b/extensions/sharing/pkg/config/parser/parse.go new file mode 100644 index 0000000000..afc4d88b8e --- /dev/null +++ b/extensions/sharing/pkg/config/parser/parse.go @@ -0,0 +1,58 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/sharing/pkg/config" + "github.com/owncloud/ocis/extensions/sharing/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.PublicSharingDriver == "cs3" && cfg.PublicSharingDrivers.CS3.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + + if cfg.PublicSharingDriver == "cs3" && cfg.PublicSharingDrivers.CS3.ServiceUserID == "" { + return shared.MissingMetadataUserID(cfg.Service.Name) + } + + if cfg.UserSharingDriver == "cs3" && cfg.UserSharingDrivers.CS3.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + + if cfg.UserSharingDriver == "cs3" && cfg.UserSharingDrivers.CS3.ServiceUserID == "" { + return shared.MissingMetadataUserID(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/sharing/pkg/config/reva.go b/extensions/sharing/pkg/config/reva.go new file mode 100644 index 0000000000..7bb95d858a --- /dev/null +++ b/extensions/sharing/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;SHARING_JWT_SECRET"` +} diff --git a/extensions/storage-metadata/pkg/command/command.go b/extensions/storage-metadata/pkg/command/command.go index 06e5c22454..54eff79d45 100644 --- a/extensions/storage-metadata/pkg/command/command.go +++ b/extensions/storage-metadata/pkg/command/command.go @@ -3,20 +3,22 @@ package command import ( "context" "flag" + "fmt" "os" "path" - "github.com/owncloud/ocis/ocis-pkg/log" - "github.com/owncloud/ocis/ocis-pkg/sync" - "github.com/owncloud/ocis/ocis-pkg/tracing" - + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/cs3org/reva/v2/cmd/revad/runtime" "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/storage-metadata/pkg/config" + "github.com/owncloud/ocis/extensions/storage-metadata/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" "github.com/owncloud/ocis/extensions/storage/pkg/service/external" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/log" + "github.com/owncloud/ocis/ocis-pkg/sync" + "github.com/owncloud/ocis/ocis-pkg/tracing" "github.com/owncloud/ocis/ocis-pkg/version" "github.com/thejerf/suture/v4" "github.com/urfave/cli/v2" @@ -30,6 +32,13 @@ func StorageMetadata(cfg *config.Config) *cli.Command { Name: "storage-metadata", Usage: "start storage-metadata service", Category: "extensions", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -124,17 +133,81 @@ func storageMetadataFromStruct(c *cli.Context, cfg *config.Config) map[string]in "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ "network": cfg.GRPC.Protocol, "address": cfg.GRPC.Addr, - "interceptors": map[string]interface{}{ - "log": map[string]interface{}{}, - }, "services": map[string]interface{}{ + "gateway": map[string]interface{}{ + // registries are located on the gateway + "authregistrysvc": cfg.GRPC.Addr, + "storageregistrysvc": cfg.GRPC.Addr, + // user metadata is located on the users services + "userprovidersvc": cfg.GRPC.Addr, + "groupprovidersvc": cfg.GRPC.Addr, + "permissionssvc": cfg.GRPC.Addr, + // other + "disable_home_creation_on_login": true, // metadata manually creates a space + // metadata always uses the simple upload, so no transfer secret or datagateway needed + }, + "userprovider": map[string]interface{}{ + "driver": "memory", + "drivers": map[string]interface{}{ + "memory": map[string]interface{}{ + "users": map[string]interface{}{ + "serviceuser": map[string]interface{}{ + "id": map[string]interface{}{ + "opaqueId": cfg.MetadataUserID, + "idp": "internal", + "type": userpb.UserType_USER_TYPE_PRIMARY, + }, + "username": "serviceuser", + "display_name": "System User", + }, + }, + }, + }, + }, + "authregistry": map[string]interface{}{ + "driver": "static", + "drivers": map[string]interface{}{ + "static": map[string]interface{}{ + "rules": map[string]interface{}{ + "machine": cfg.GRPC.Addr, + }, + }, + }, + }, + "authprovider": map[string]interface{}{ + "auth_manager": "machine", + "auth_managers": map[string]interface{}{ + "machine": map[string]interface{}{ + "api_key": cfg.MachineAuthAPIKey, + "gateway_addr": cfg.GRPC.Addr, + }, + }, + }, + "permissions": map[string]interface{}{ + "driver": "demo", + "drivers": map[string]interface{}{ + "demo": map[string]interface{}{}, + }, + }, + "storageregistry": map[string]interface{}{ + "driver": "static", + "drivers": map[string]interface{}{ + "static": map[string]interface{}{ + "rules": map[string]interface{}{ + "/": map[string]interface{}{ + "address": cfg.GRPC.Addr, + }, + }, + }, + }, + }, "storageprovider": map[string]interface{}{ "driver": cfg.Driver, "drivers": config.MetadataDrivers(cfg), @@ -146,7 +219,7 @@ func storageMetadataFromStruct(c *cli.Context, cfg *config.Config) map[string]in "http": map[string]interface{}{ "network": cfg.HTTP.Protocol, "address": cfg.HTTP.Addr, - // TODO build services dynamically + // no datagateway needed as the metadata clients directly talk to the dataprovider with the simple protocol "services": map[string]interface{}{ "dataprovider": map[string]interface{}{ "prefix": "data", diff --git a/extensions/storage-metadata/pkg/config/config.go b/extensions/storage-metadata/pkg/config/config.go index 526a4eabc0..8c4475600f 100644 --- a/extensions/storage-metadata/pkg/config/config.go +++ b/extensions/storage-metadata/pkg/config/config.go @@ -12,20 +12,24 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` HTTP HTTPConfig `yaml:"http"` - Context context.Context - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool + Context context.Context `yaml:"context"` + + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"STORAGE_METADATA_MACHINE_AUTH_API_KEY"` + MetadataUserID string `yaml:"metadata_user_id"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` Driver string `yaml:"driver" env:"STORAGE_METADATA_DRIVER" desc:"The driver which should be used by the service"` Drivers Drivers `yaml:"drivers"` - DataServerURL string - TempFolder string - DataProviderInsecure bool `env:"OCIS_INSECURE;STORAGE_METADATA_DATAPROVIDER_INSECURE"` + DataServerURL string `yaml:"data_server_url"` + TempFolder string `yaml:"temp_folder"` + DataProviderInsecure bool `yaml:"data_provider_insecure" env:"OCIS_INSECURE;STORAGE_METADATA_DATAPROVIDER_INSECURE"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;STORAGE_METADATA_TRACING_ENABLED" desc:"Activates tracing."` @@ -58,8 +62,8 @@ type GRPCConfig struct { } type HTTPConfig struct { - Addr string `yaml:"addr" env:"STORAGE_METADATA_GRPC_ADDR" desc:"The address of the grpc service."` - Protocol string `yaml:"protocol" env:"STORAGE_METADATA_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."` + Addr string `yaml:"addr" env:"STORAGE_METADATA_HTTP_ADDR" desc:"The address of the http service."` + Protocol string `yaml:"protocol" env:"STORAGE_METADATA_HTTP_PROTOCOL" desc:"The transport protocol of the http service."` } type Drivers struct { diff --git a/extensions/storage-metadata/pkg/config/defaults/defaultconfig.go b/extensions/storage-metadata/pkg/config/defaults/defaultconfig.go index 298d31eb56..4f274aa0ca 100644 --- a/extensions/storage-metadata/pkg/config/defaults/defaultconfig.go +++ b/extensions/storage-metadata/pkg/config/defaults/defaultconfig.go @@ -10,9 +10,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -35,11 +34,12 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "storage-metadata", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - TempFolder: filepath.Join(defaults.BaseDataPath(), "tmp", "metadata"), - DataServerURL: "http://localhost:9216/data", - Driver: "ocis", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + TempFolder: filepath.Join(defaults.BaseDataPath(), "tmp", "metadata"), + DataServerURL: "http://localhost:9216/data", + Driver: "ocis", Drivers: config.Drivers{ EOS: config.EOSDriver{ Root: "/eos/dockertest/reva", @@ -59,7 +59,7 @@ func DefaultConfig() *config.Config { SecProtocol: "", Keytab: "", SingleUsername: "", - GatewaySVC: "127.0.0.1:9142", + GatewaySVC: "127.0.0.1:9215", }, Local: config.LocalDriver{ Root: filepath.Join(defaults.BaseDataPath(), "storage", "local", "metadata"), @@ -71,12 +71,12 @@ func DefaultConfig() *config.Config { Root: filepath.Join(defaults.BaseDataPath(), "storage", "metadata"), UserLayout: "{{.Id.OpaqueId}}", Region: "default", - PermissionsEndpoint: "127.0.0.1:9191", + PermissionsEndpoint: "127.0.0.1:9215", }, OCIS: config.OCISDriver{ Root: filepath.Join(defaults.BaseDataPath(), "storage", "metadata"), UserLayout: "{{.Id.OpaqueId}}", - PermissionsEndpoint: "127.0.0.1:9191", + PermissionsEndpoint: "127.0.0.1:9215", }, }, } @@ -105,6 +105,31 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } + + if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } + + if cfg.MetadataUserID == "" && cfg.Commons != nil && cfg.Commons.MetadataUserID != "" { + cfg.MetadataUserID = cfg.Commons.MetadataUserID + } + } func Sanitize(cfg *config.Config) { diff --git a/extensions/storage-metadata/pkg/config/parser/parse.go b/extensions/storage-metadata/pkg/config/parser/parse.go new file mode 100644 index 0000000000..413bbd52c5 --- /dev/null +++ b/extensions/storage-metadata/pkg/config/parser/parse.go @@ -0,0 +1,49 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/storage-metadata/pkg/config" + "github.com/owncloud/ocis/extensions/storage-metadata/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError(cfg.Service.Name) + } + + if cfg.MetadataUserID == "" { + return shared.MissingMetadataUserID(cfg.Service.Name) + } + return nil +} diff --git a/extensions/storage-metadata/pkg/config/reva.go b/extensions/storage-metadata/pkg/config/reva.go new file mode 100644 index 0000000000..3094a80135 --- /dev/null +++ b/extensions/storage-metadata/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;STORAGE_METADATA_JWT_SECRET"` +} diff --git a/extensions/storage-publiclink/pkg/command/storagepubliclink.go b/extensions/storage-publiclink/pkg/command/storagepubliclink.go index 5991885449..06fe7ada8a 100644 --- a/extensions/storage-publiclink/pkg/command/storagepubliclink.go +++ b/extensions/storage-publiclink/pkg/command/storagepubliclink.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" @@ -10,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/storage-publiclink/pkg/config" + "github.com/owncloud/ocis/extensions/storage-publiclink/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/log" @@ -25,6 +27,13 @@ func StoragePublicLink(cfg *config.Config) *cli.Command { Name: "storage-public-link", Usage: "start storage-public-link service", Category: "extensions", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -94,8 +103,8 @@ func storagePublicLinkConfigFromStruct(c *cli.Context, cfg *config.Config) map[s "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/storage-publiclink/pkg/config/config.go b/extensions/storage-publiclink/pkg/config/config.go index 3766e35ead..92d412a690 100644 --- a/extensions/storage-publiclink/pkg/config/config.go +++ b/extensions/storage-publiclink/pkg/config/config.go @@ -12,29 +12,31 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - Context context.Context - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool - AuthProvider AuthProvider - StorageProvider StorageProvider + Context context.Context `yaml:"context"` + + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` + AuthProvider AuthProvider `yaml:"auth_provider"` + StorageProvider StorageProvider `yaml:"storage_provider"` } type Tracing struct { - Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;STORAGE_METADATA_TRACING_ENABLED" desc:"Activates tracing."` - Type string `yaml:"type" env:"OCIS_TRACING_TYPE;STORAGE_METADATA_TRACING_TYPE"` - Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;STORAGE_METADATA_TRACING_ENDPOINT" desc:"The endpoint to the tracing collector."` - Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;STORAGE_METADATA_TRACING_COLLECTOR"` + Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;STORAGE_PUBLICLINK_TRACING_ENABLED" desc:"Activates tracing."` + Type string `yaml:"type" env:"OCIS_TRACING_TYPE;STORAGE_PUBLICLINK_TRACING_TYPE"` + Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;STORAGE_PUBLICLINK_TRACING_ENDPOINT" desc:"The endpoint to the tracing collector."` + Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;STORAGE_PUBLICLINK_TRACING_COLLECTOR"` } type Logging struct { - Level string `yaml:"level" env:"OCIS_LOG_LEVEL;STORAGE_METADATA_LOG_LEVEL" desc:"The log level."` - Pretty bool `yaml:"pretty" env:"OCIS_LOG_PRETTY;STORAGE_METADATA_LOG_PRETTY" desc:"Activates pretty log output."` - Color bool `yaml:"color" env:"OCIS_LOG_COLOR;STORAGE_METADATA_LOG_COLOR" desc:"Activates colorized log output."` - File string `yaml:"file" env:"OCIS_LOG_FILE;STORAGE_METADATA_LOG_FILE" desc:"The target log file."` + Level string `yaml:"level" env:"OCIS_LOG_LEVEL;STORAGE_PUBLICLINK_LOG_LEVEL" desc:"The log level."` + Pretty bool `yaml:"pretty" env:"OCIS_LOG_PRETTY;STORAGE_PUBLICLINK_LOG_PRETTY" desc:"Activates pretty log output."` + Color bool `yaml:"color" env:"OCIS_LOG_COLOR;STORAGE_PUBLICLINK_LOG_COLOR" desc:"Activates colorized log output."` + File string `yaml:"file" env:"OCIS_LOG_FILE;STORAGE_PUBLICLINK_LOG_FILE" desc:"The target log file."` } type Service struct { @@ -42,15 +44,15 @@ type Service struct { } type Debug struct { - Addr string `yaml:"addr" env:"STORAGE_METADATA_DEBUG_ADDR"` - Token string `yaml:"token" env:"STORAGE_METADATA_DEBUG_TOKEN"` - Pprof bool `yaml:"pprof" env:"STORAGE_METADATA_DEBUG_PPROF"` - Zpages bool `yaml:"zpages" env:"STORAGE_METADATA_DEBUG_ZPAGES"` + Addr string `yaml:"addr" env:"STORAGE_PUBLICLINK_DEBUG_ADDR"` + Token string `yaml:"token" env:"STORAGE_PUBLICLINK_DEBUG_TOKEN"` + Pprof bool `yaml:"pprof" env:"STORAGE_PUBLICLINK_DEBUG_PPROF"` + Zpages bool `yaml:"zpages" env:"STORAGE_PUBLICLINK_DEBUG_ZPAGES"` } type GRPCConfig struct { - Addr string `yaml:"addr" env:"STORAGE_METADATA_GRPC_ADDR" desc:"The address of the grpc service."` - Protocol string `yaml:"protocol" env:"STORAGE_METADATA_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."` + Addr string `yaml:"addr" env:"STORAGE_PUBLICLINK_GRPC_ADDR" desc:"The address of the grpc service."` + Protocol string `yaml:"protocol" env:"STORAGE_PUBLICLINK_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."` } type AuthProvider struct { diff --git a/extensions/storage-publiclink/pkg/config/defaults/defaultconfig.go b/extensions/storage-publiclink/pkg/config/defaults/defaultconfig.go index bd2a7cc05c..47b729c05a 100644 --- a/extensions/storage-publiclink/pkg/config/defaults/defaultconfig.go +++ b/extensions/storage-publiclink/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -27,8 +26,9 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "storage-publiclink", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, AuthProvider: config.AuthProvider{ GatewayEndpoint: "127.0.0.1:9142", }, @@ -62,6 +62,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/storage-publiclink/pkg/config/parser/parse.go b/extensions/storage-publiclink/pkg/config/parser/parse.go new file mode 100644 index 0000000000..f0e7cda992 --- /dev/null +++ b/extensions/storage-publiclink/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/storage-publiclink/pkg/config" + "github.com/owncloud/ocis/extensions/storage-publiclink/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/storage-publiclink/pkg/config/reva.go b/extensions/storage-publiclink/pkg/config/reva.go new file mode 100644 index 0000000000..306ae4f262 --- /dev/null +++ b/extensions/storage-publiclink/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;STORAGE_PUBLICLINK_JWT_SECRET"` +} diff --git a/extensions/storage-shares/pkg/command/command.go b/extensions/storage-shares/pkg/command/command.go index b6804326f3..6964706456 100644 --- a/extensions/storage-shares/pkg/command/command.go +++ b/extensions/storage-shares/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" @@ -14,6 +15,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/storage-shares/pkg/config" + "github.com/owncloud/ocis/extensions/storage-shares/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/thejerf/suture/v4" @@ -25,6 +27,13 @@ func StorageShares(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "storage-shares", Usage: "start storage-shares service", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -96,8 +105,8 @@ func storageSharesConfigFromStruct(c *cli.Context, cfg *config.Config) map[strin "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/storage-shares/pkg/config/config.go b/extensions/storage-shares/pkg/config/config.go index 8c13456013..4677edef2e 100644 --- a/extensions/storage-shares/pkg/config/config.go +++ b/extensions/storage-shares/pkg/config/config.go @@ -12,30 +12,31 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` HTTP HTTPConfig `yaml:"http"` - Context context.Context - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool - ReadOnly bool - SharesProviderEndpoint string + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + Context context.Context `yaml:"context"` + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` + ReadOnly bool `yaml:"readonly"` + SharesProviderEndpoint string `yaml:"shares_provider_endpoint"` } type Tracing struct { - Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;STORAGE_METADATA_TRACING_ENABLED" desc:"Activates tracing."` - Type string `yaml:"type" env:"OCIS_TRACING_TYPE;STORAGE_METADATA_TRACING_TYPE"` - Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;STORAGE_METADATA_TRACING_ENDPOINT" desc:"The endpoint to the tracing collector."` - Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;STORAGE_METADATA_TRACING_COLLECTOR"` + Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;STORAGE_SHARES_TRACING_ENABLED" desc:"Activates tracing."` + Type string `yaml:"type" env:"OCIS_TRACING_TYPE;STORAGE_SHARES_TRACING_TYPE"` + Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;STORAGE_SHARES_TRACING_ENDPOINT" desc:"The endpoint to the tracing collector."` + Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;STORAGE_SHARES_TRACING_COLLECTOR"` } type Logging struct { - Level string `yaml:"level" env:"OCIS_LOG_LEVEL;STORAGE_METADATA_LOG_LEVEL" desc:"The log level."` - Pretty bool `yaml:"pretty" env:"OCIS_LOG_PRETTY;STORAGE_METADATA_LOG_PRETTY" desc:"Activates pretty log output."` - Color bool `yaml:"color" env:"OCIS_LOG_COLOR;STORAGE_METADATA_LOG_COLOR" desc:"Activates colorized log output."` - File string `yaml:"file" env:"OCIS_LOG_FILE;STORAGE_METADATA_LOG_FILE" desc:"The target log file."` + Level string `yaml:"level" env:"OCIS_LOG_LEVEL;STORAGE_SHARES_LOG_LEVEL" desc:"The log level."` + Pretty bool `yaml:"pretty" env:"OCIS_LOG_PRETTY;STORAGE_SHARES_LOG_PRETTY" desc:"Activates pretty log output."` + Color bool `yaml:"color" env:"OCIS_LOG_COLOR;STORAGE_SHARES_LOG_COLOR" desc:"Activates colorized log output."` + File string `yaml:"file" env:"OCIS_LOG_FILE;STORAGE_SHARES_LOG_FILE" desc:"The target log file."` } type Service struct { @@ -43,18 +44,18 @@ type Service struct { } type Debug struct { - Addr string `yaml:"addr" env:"STORAGE_METADATA_DEBUG_ADDR"` - Token string `yaml:"token" env:"STORAGE_METADATA_DEBUG_TOKEN"` - Pprof bool `yaml:"pprof" env:"STORAGE_METADATA_DEBUG_PPROF"` - Zpages bool `yaml:"zpages" env:"STORAGE_METADATA_DEBUG_ZPAGES"` + Addr string `yaml:"addr" env:"STORAGE_SHARES_DEBUG_ADDR"` + Token string `yaml:"token" env:"STORAGE_SHARES_DEBUG_TOKEN"` + Pprof bool `yaml:"pprof" env:"STORAGE_SHARES_DEBUG_PPROF"` + Zpages bool `yaml:"zpages" env:"STORAGE_SHARES_DEBUG_ZPAGES"` } type GRPCConfig struct { - Addr string `yaml:"addr" env:"STORAGE_METADATA_GRPC_ADDR" desc:"The address of the grpc service."` - Protocol string `yaml:"protocol" env:"STORAGE_METADATA_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."` + Addr string `yaml:"addr" env:"STORAGE_SHARES_GRPC_ADDR" desc:"The address of the grpc service."` + Protocol string `yaml:"protocol" env:"STORAGE_SHARES_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."` } type HTTPConfig struct { - Addr string `yaml:"addr" env:"STORAGE_METADATA_GRPC_ADDR" desc:"The address of the grpc service."` - Protocol string `yaml:"protocol" env:"STORAGE_METADATA_GRPC_PROTOCOL" desc:"The transport protocol of the grpc service."` + Addr string `yaml:"addr" env:"STORAGE_SHARES_HTTP_ADDR" desc:"The address of the grpc service."` + Protocol string `yaml:"protocol" env:"STORAGE_SHARES_HTTP_PROTOCOL" desc:"The transport protocol of the grpc service."` } diff --git a/extensions/storage-shares/pkg/config/defaults/defaultconfig.go b/extensions/storage-shares/pkg/config/defaults/defaultconfig.go index bf56e76cc6..40aba54cfd 100644 --- a/extensions/storage-shares/pkg/config/defaults/defaultconfig.go +++ b/extensions/storage-shares/pkg/config/defaults/defaultconfig.go @@ -6,9 +6,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -29,10 +28,11 @@ func DefaultConfig() *config.Config { Protocol: "tcp", }, Service: config.Service{ - Name: "storage-metadata", + Name: "storage-shares", + }, + Reva: &config.Reva{ + Address: "127.0.0.1:9142", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", ReadOnly: false, SharesProviderEndpoint: "localhost:9150", } @@ -61,6 +61,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/storage-shares/pkg/config/parser/parse.go b/extensions/storage-shares/pkg/config/parser/parse.go new file mode 100644 index 0000000000..6b0efc7aef --- /dev/null +++ b/extensions/storage-shares/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/storage-shares/pkg/config" + "github.com/owncloud/ocis/extensions/storage-shares/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/storage-shares/pkg/config/reva.go b/extensions/storage-shares/pkg/config/reva.go new file mode 100644 index 0000000000..75b30df05a --- /dev/null +++ b/extensions/storage-shares/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;STORAGE_SHARES_JWT_SECRET"` +} diff --git a/extensions/storage-users/pkg/command/command.go b/extensions/storage-users/pkg/command/command.go index 564dd4e558..5e48a2db03 100644 --- a/extensions/storage-users/pkg/command/command.go +++ b/extensions/storage-users/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" @@ -10,6 +11,7 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" "github.com/owncloud/ocis/extensions/storage-users/pkg/config" + "github.com/owncloud/ocis/extensions/storage-users/pkg/config/parser" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/log" @@ -24,6 +26,13 @@ func StorageUsers(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "storage-users", Usage: "start storage-users service", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -95,8 +104,8 @@ func storageUsersConfigFromStruct(c *cli.Context, cfg *config.Config) map[string "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/storage-users/pkg/config/config.go b/extensions/storage-users/pkg/config/config.go index 1cbe616344..7cb2888148 100644 --- a/extensions/storage-users/pkg/config/config.go +++ b/extensions/storage-users/pkg/config/config.go @@ -12,24 +12,26 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` HTTP HTTPConfig `yaml:"http"` - Context context.Context - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + Context context.Context `yaml:"context"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` Driver string `yaml:"driver" env:"STORAGE_USERS_DRIVER" desc:"The storage driver which should be used by the service"` Drivers Drivers `yaml:"drivers"` - DataServerURL string - TempFolder string - DataProviderInsecure bool `env:"OCIS_INSECURE;STORAGE_USERS_DATAPROVIDER_INSECURE"` - Events Events - MountID string - ExposeDataServer bool - ReadOnly bool + DataServerURL string `yaml:"data_server_url"` + TempFolder string `yaml:"temp_folder"` + DataProviderInsecure bool `yaml:"data_provider_insecure" env:"OCIS_INSECURE;STORAGE_USERS_DATAPROVIDER_INSECURE"` + Events Events `yaml:"events"` + MountID string `yaml:"mount_id"` + ExposeDataServer bool `yaml:"expose_data_server"` + ReadOnly bool `yaml:"readonly"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;STORAGE_USERS_TRACING_ENABLED" desc:"Activates tracing."` diff --git a/extensions/storage-users/pkg/config/defaults/defaultconfig.go b/extensions/storage-users/pkg/config/defaults/defaultconfig.go index 8dc305fced..b29e9daa98 100644 --- a/extensions/storage-users/pkg/config/defaults/defaultconfig.go +++ b/extensions/storage-users/pkg/config/defaults/defaultconfig.go @@ -10,9 +10,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -36,12 +35,13 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "storage-users", }, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - TempFolder: filepath.Join(defaults.BaseDataPath(), "tmp", "users"), - DataServerURL: "http://localhost:9158/data", - MountID: "1284d238-aa92-42ce-bdc4-0b0000009157", - Driver: "ocis", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + TempFolder: filepath.Join(defaults.BaseDataPath(), "tmp", "users"), + DataServerURL: "http://localhost:9158/data", + MountID: "1284d238-aa92-42ce-bdc4-0b0000009157", + Driver: "ocis", Drivers: config.Drivers{ EOS: config.EOSDriver{ Root: "/eos/dockertest/reva", @@ -124,6 +124,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/storage-users/pkg/config/parser/parse.go b/extensions/storage-users/pkg/config/parser/parse.go new file mode 100644 index 0000000000..b6a55e1aef --- /dev/null +++ b/extensions/storage-users/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/storage-users/pkg/config" + "github.com/owncloud/ocis/extensions/storage-users/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/storage-users/pkg/config/reva.go b/extensions/storage-users/pkg/config/reva.go new file mode 100644 index 0000000000..fd15399fe2 --- /dev/null +++ b/extensions/storage-users/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;STORAGE_USERS_JWT_SECRET"` +} diff --git a/extensions/storage/pkg/config/config.go b/extensions/storage/pkg/config/config.go index cfd35175e7..c3a626e40f 100644 --- a/extensions/storage/pkg/config/config.go +++ b/extensions/storage/pkg/config/config.go @@ -188,7 +188,7 @@ type Auth struct { // DataGatewayPort has a public url type DataGatewayPort struct { Port - PublicURL string `yaml:""` + PublicURL string } type DataProvider struct { diff --git a/extensions/storage/pkg/config/defaults/defaultconfig.go b/extensions/storage/pkg/config/defaults/defaultconfig.go index c14ac52f0d..0e2faf43df 100644 --- a/extensions/storage/pkg/config/defaults/defaultconfig.go +++ b/extensions/storage/pkg/config/defaults/defaultconfig.go @@ -20,10 +20,8 @@ const ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -34,9 +32,7 @@ func DefaultConfig() *config.Config { Addr: "127.0.0.1:9109", }, Reva: config.Reva{ - JWTSecret: "Pive-Fumkiu4", SkipUserGroupsInToken: false, - TransferSecret: "replace-me-with-a-transfer-secret", TransferExpires: 24 * 60 * 60, OIDC: config.OIDC{ Issuer: defaultPublicURL, @@ -57,7 +53,6 @@ func DefaultConfig() *config.Config { UserObjectClass: "inetOrgPerson", GroupObjectClass: "groupOfNames", BindDN: "uid=reva,ou=sysusers,o=libregraph-idm", - BindPassword: "reva", IDP: defaultPublicURL, UserSchema: config.LDAPUserSchema{ ID: "ownclouduuid", @@ -81,7 +76,6 @@ func DefaultConfig() *config.Config { }, UserOwnCloudSQL: config.UserOwnCloudSQL{ DBUsername: "owncloud", - DBPassword: "secret", DBHost: "mysql", DBPort: 3306, DBName: "owncloud", @@ -328,9 +322,7 @@ func DefaultConfig() *config.Config { Services: []string{"authprovider"}, Endpoint: "localhost:9166", }, - AuthMachineConfig: config.AuthMachineConfig{ - MachineAuthAPIKey: "change-me-please", - }, + AuthMachineConfig: config.AuthMachineConfig{}, Sharing: config.Sharing{ Port: config.Port{ Endpoint: "localhost:9150", @@ -339,9 +331,9 @@ func DefaultConfig() *config.Config { GRPCAddr: "127.0.0.1:9150", Services: []string{"usershareprovider", "publicshareprovider"}, }, - CS3ProviderAddr: "127.0.0.1:9215", + CS3ProviderAddr: "127.0.0.1:9215", // metadata storage CS3ServiceUser: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - CS3ServiceUserIdp: "https://localhost:9200", + CS3ServiceUserIdp: "internal", UserDriver: "json", UserJSONFile: path.Join(defaults.BaseDataPath(), "storage", "shares.json"), UserSQLUsername: "", @@ -451,7 +443,6 @@ func DefaultConfig() *config.Config { GatewaySVC: defaultGatewayAddr, Insecure: false, // true? Timeout: 84300, - JWTSecret: "Pive-Fumkiu4", }, Tracing: config.Tracing{ Service: "storage", @@ -462,9 +453,7 @@ func DefaultConfig() *config.Config { } func EnsureDefaults(cfg *config.Config) { - // TODO: IMPLEMENT ME! } func Sanitize(cfg *config.Config) { - // TODO: IMPLEMENT ME! } diff --git a/extensions/storage/pkg/config/parser/parse.go b/extensions/storage/pkg/config/parser/parse.go new file mode 100644 index 0000000000..d486f6dad4 --- /dev/null +++ b/extensions/storage/pkg/config/parser/parse.go @@ -0,0 +1,37 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/storage-metadata/pkg/config" + "github.com/owncloud/ocis/extensions/storage-metadata/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + return nil +} diff --git a/extensions/store/pkg/command/health.go b/extensions/store/pkg/command/health.go index 7bf3ba8f46..341f59317c 100644 --- a/extensions/store/pkg/command/health.go +++ b/extensions/store/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/store/pkg/command/server.go b/extensions/store/pkg/command/server.go index ac14affd2c..a2995507e7 100644 --- a/extensions/store/pkg/command/server.go +++ b/extensions/store/pkg/command/server.go @@ -24,7 +24,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/store/pkg/config/defaults/defaultconfig.go b/extensions/store/pkg/config/defaults/defaultconfig.go index 1d84c1c474..8932d4266a 100644 --- a/extensions/store/pkg/config/defaults/defaultconfig.go +++ b/extensions/store/pkg/config/defaults/defaultconfig.go @@ -9,10 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/store/pkg/config/parser/parse.go b/extensions/store/pkg/config/parser/parse.go index 7c9f02bda3..68045ecf75 100644 --- a/extensions/store/pkg/config/parser/parse.go +++ b/extensions/store/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +29,10 @@ func ParseConfig(cfg *config.Config) error { // sanitize config defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/extensions/thumbnails/pkg/command/health.go b/extensions/thumbnails/pkg/command/health.go index f63d023d55..17e9358771 100644 --- a/extensions/thumbnails/pkg/command/health.go +++ b/extensions/thumbnails/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/thumbnails/pkg/command/server.go b/extensions/thumbnails/pkg/command/server.go index 8bfd35a1bd..7244a7c86c 100644 --- a/extensions/thumbnails/pkg/command/server.go +++ b/extensions/thumbnails/pkg/command/server.go @@ -24,7 +24,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/thumbnails/pkg/config/config.go b/extensions/thumbnails/pkg/config/config.go index 0afad535c6..4e65f12e82 100644 --- a/extensions/thumbnails/pkg/config/config.go +++ b/extensions/thumbnails/pkg/config/config.go @@ -42,6 +42,6 @@ type Thumbnail struct { CS3AllowInsecure bool `yaml:"cs3_allow_insecure" env:"OCIS_INSECURE;THUMBNAILS_CS3SOURCE_INSECURE"` RevaGateway string `yaml:"reva_gateway" env:"REVA_GATEWAY"` //TODO: use REVA config FontMapFile string `yaml:"font_map_file" env:"THUMBNAILS_TXT_FONTMAP_FILE"` - TransferTokenSecret string `yaml:"transfer_token" env:"THUMBNAILS_TRANSFER_TOKEN"` + TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_TOKEN;THUMBNAILS_TRANSFER_TOKEN"` DataEndpoint string `yaml:"data_endpoint" env:"THUMBNAILS_DATA_ENDPOINT"` } diff --git a/extensions/thumbnails/pkg/config/defaults/defaultconfig.go b/extensions/thumbnails/pkg/config/defaults/defaultconfig.go index c74b85065b..b24c9e3d11 100644 --- a/extensions/thumbnails/pkg/config/defaults/defaultconfig.go +++ b/extensions/thumbnails/pkg/config/defaults/defaultconfig.go @@ -9,10 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } @@ -44,7 +42,6 @@ func DefaultConfig() *config.Config { WebdavAllowInsecure: false, RevaGateway: "127.0.0.1:9142", CS3AllowInsecure: false, - TransferTokenSecret: "changemeplease", DataEndpoint: "http://127.0.0.1:9186/thumbnails/data", }, } @@ -73,6 +70,10 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Thumbnail.TransferSecret == "" && cfg.Commons != nil && cfg.Commons.TransferSecret != "" { + cfg.Thumbnail.TransferSecret = cfg.Commons.TransferSecret + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/thumbnails/pkg/config/parser/parse.go b/extensions/thumbnails/pkg/config/parser/parse.go index 4ed7325534..4c47c635dd 100644 --- a/extensions/thumbnails/pkg/config/parser/parse.go +++ b/extensions/thumbnails/pkg/config/parser/parse.go @@ -6,11 +6,12 @@ import ( "github.com/owncloud/ocis/extensions/thumbnails/pkg/config" "github.com/owncloud/ocis/extensions/thumbnails/pkg/config/defaults" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -30,5 +31,13 @@ func ParseConfig(cfg *config.Config) error { // sanitize config defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.Thumbnail.TransferSecret == "" { + return shared.MissingRevaTransferSecretError(cfg.Service.Name) + } + return nil } diff --git a/extensions/thumbnails/pkg/service/grpc/v0/service.go b/extensions/thumbnails/pkg/service/grpc/v0/service.go index b5f34f32fd..22a3465c93 100644 --- a/extensions/thumbnails/pkg/service/grpc/v0/service.go +++ b/extensions/thumbnails/pkg/service/grpc/v0/service.go @@ -48,8 +48,8 @@ func NewService(opts ...Option) decorators.DecoratedService { preprocessorOpts: PreprocessorOpts{ TxtFontFileMap: options.Config.Thumbnail.FontMapFile, }, - dataEndpoint: options.Config.Thumbnail.DataEndpoint, - transferTokenSecret: options.Config.Thumbnail.TransferTokenSecret, + dataEndpoint: options.Config.Thumbnail.DataEndpoint, + transferSecret: options.Config.Thumbnail.TransferSecret, } return svc @@ -57,15 +57,15 @@ func NewService(opts ...Option) decorators.DecoratedService { // Thumbnail implements the GRPC handler. type Thumbnail struct { - serviceID string - dataEndpoint string - transferTokenSecret string - manager thumbnail.Manager - webdavSource imgsource.Source - cs3Source imgsource.Source - logger log.Logger - cs3Client gateway.GatewayAPIClient - preprocessorOpts PreprocessorOpts + serviceID string + dataEndpoint string + transferSecret string + manager thumbnail.Manager + webdavSource imgsource.Source + cs3Source imgsource.Source + logger log.Logger + cs3Client gateway.GatewayAPIClient + preprocessorOpts PreprocessorOpts } type PreprocessorOpts struct { @@ -113,7 +113,7 @@ func (g Thumbnail) GetThumbnail(ctx context.Context, req *thumbnailssvc.GetThumb } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - transferToken, err := token.SignedString([]byte(g.transferTokenSecret)) + transferToken, err := token.SignedString([]byte(g.transferSecret)) if err != nil { g.logger.Error(). Err(err). diff --git a/extensions/thumbnails/pkg/service/http/v0/service.go b/extensions/thumbnails/pkg/service/http/v0/service.go index 864dca0ae8..944020cb5a 100644 --- a/extensions/thumbnails/pkg/service/http/v0/service.go +++ b/extensions/thumbnails/pkg/service/http/v0/service.go @@ -102,7 +102,7 @@ func (s Thumbnails) TransferTokenValidator(next http.Handler) http.Handler { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } - return []byte(s.config.Thumbnail.TransferTokenSecret), nil + return []byte(s.config.Thumbnail.TransferSecret), nil }) if err != nil { s.logger.Error(). diff --git a/extensions/user/pkg/command/command.go b/extensions/user/pkg/command/command.go index a77f23f4c1..27e7cabfab 100644 --- a/extensions/user/pkg/command/command.go +++ b/extensions/user/pkg/command/command.go @@ -3,6 +3,7 @@ package command import ( "context" "flag" + "fmt" "os" "path" "path/filepath" @@ -12,6 +13,7 @@ import ( "github.com/oklog/run" "github.com/owncloud/ocis/extensions/storage/pkg/server/debug" "github.com/owncloud/ocis/extensions/user/pkg/config" + "github.com/owncloud/ocis/extensions/user/pkg/config/parser" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/ldap" "github.com/owncloud/ocis/ocis-pkg/log" @@ -26,6 +28,13 @@ func User(cfg *config.Config) *cli.Command { return &cli.Command{ Name: "users", Usage: "start users service", + Before: func(ctx *cli.Context) error { + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err + }, Action: func(c *cli.Context) error { logCfg := cfg.Logging logger := log.NewLogger( @@ -116,8 +125,8 @@ func usersConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]interf "tracing_service_name": c.Command.Name, }, "shared": map[string]interface{}{ - "jwt_secret": cfg.JWTSecret, - "gatewaysvc": cfg.GatewayEndpoint, + "jwt_secret": cfg.TokenManager.JWTSecret, + "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ diff --git a/extensions/user/pkg/config/config.go b/extensions/user/pkg/config/config.go index fdb08f931d..41cc0ab6e6 100644 --- a/extensions/user/pkg/config/config.go +++ b/extensions/user/pkg/config/config.go @@ -8,16 +8,17 @@ type Config struct { Tracing *Tracing `yaml:"tracing"` Logging *Logging `yaml:"log"` Debug Debug `yaml:"debug"` - Supervised bool + Supervised bool `yaml:"-"` GRPC GRPCConfig `yaml:"grpc"` - JWTSecret string - GatewayEndpoint string - SkipUserGroupsInToken bool - UsersCacheExpiration int - Driver string - Drivers Drivers + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + + SkipUserGroupsInToken bool `yaml:"skip_user_groups_in_token"` + UsersCacheExpiration int `yaml:"users_cache_expiration"` + Driver string `yaml:"driver"` + Drivers Drivers `yaml:"drivers"` } type Tracing struct { Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;USERS_TRACING_ENABLED" desc:"Activates tracing."` @@ -64,7 +65,7 @@ type LDAPDriver struct { CACert string `env:"LDAP_CACERT;USERS_LDAP_CACERT"` Insecure bool `env:"LDAP_INSECURE;USERS_LDAP_INSECURE"` BindDN string `env:"LDAP_BIND_DN;USERS_LDAP_BIND_DN"` - BindPassword string `env:"LDAP_BIND_PASSWORD;USERS_LDAP_BIND_PASSWORD"` + BindPassword string `yaml:"bind_password" env:"LDAP_BIND_PASSWORD;USERS_LDAP_BIND_PASSWORD"` UserBaseDN string `env:"LDAP_USER_BASE_DN;USERS_LDAP_USER_BASE_DN"` GroupBaseDN string `env:"LDAP_GROUP_BASE_DN;USERS_LDAP_GROUP_BASE_DN"` UserScope string `env:"LDAP_USER_SCOPE;USERS_LDAP_USER_SCOPE"` diff --git a/extensions/user/pkg/config/defaults/defaultconfig.go b/extensions/user/pkg/config/defaults/defaultconfig.go index 20a486f47a..b7212abd0b 100644 --- a/extensions/user/pkg/config/defaults/defaultconfig.go +++ b/extensions/user/pkg/config/defaults/defaultconfig.go @@ -9,9 +9,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) - + Sanitize(cfg) return cfg } @@ -31,9 +30,10 @@ func DefaultConfig() *config.Config { Name: "user", }, UsersCacheExpiration: 5, - GatewayEndpoint: "127.0.0.1:9142", - JWTSecret: "Pive-Fumkiu4", - Driver: "ldap", + Reva: &config.Reva{ + Address: "127.0.0.1:9142", + }, + Driver: "ldap", Drivers: config.Drivers{ LDAP: config.LDAPDriver{ URI: "ldaps://localhost:9235", @@ -49,7 +49,6 @@ func DefaultConfig() *config.Config { UserObjectClass: "inetOrgPerson", GroupObjectClass: "groupOfNames", BindDN: "uid=reva,ou=sysusers,o=libregraph-idm", - BindPassword: "reva", IDP: "https://localhost:9200", UserSchema: config.LDAPUserSchema{ ID: "ownclouduuid", @@ -108,6 +107,22 @@ func EnsureDefaults(cfg *config.Config) { } else if cfg.Tracing == nil { cfg.Tracing = &config.Tracing{} } + + if cfg.Reva == nil && cfg.Commons != nil && cfg.Commons.Reva != nil { + cfg.Reva = &config.Reva{ + Address: cfg.Commons.Reva.Address, + } + } else if cfg.Reva == nil { + cfg.Reva = &config.Reva{} + } + + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } } func Sanitize(cfg *config.Config) { diff --git a/extensions/user/pkg/config/parser/parse.go b/extensions/user/pkg/config/parser/parse.go new file mode 100644 index 0000000000..2b5f8030a5 --- /dev/null +++ b/extensions/user/pkg/config/parser/parse.go @@ -0,0 +1,46 @@ +package parser + +import ( + "errors" + + "github.com/owncloud/ocis/extensions/user/pkg/config" + "github.com/owncloud/ocis/extensions/user/pkg/config/defaults" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" + + "github.com/owncloud/ocis/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + if cfg.Driver == "ldap" && cfg.Drivers.LDAP.BindPassword == "" { + return shared.MissingLDAPBindPassword(cfg.Service.Name) + } + + return nil +} diff --git a/extensions/user/pkg/config/reva.go b/extensions/user/pkg/config/reva.go new file mode 100644 index 0000000000..310858a795 --- /dev/null +++ b/extensions/user/pkg/config/reva.go @@ -0,0 +1,11 @@ +package config + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;USERS_JWT_SECRET"` +} diff --git a/extensions/web/pkg/command/health.go b/extensions/web/pkg/command/health.go index 397f14da41..70e33f31e1 100644 --- a/extensions/web/pkg/command/health.go +++ b/extensions/web/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/web/pkg/command/server.go b/extensions/web/pkg/command/server.go index e62494d072..d95587aa25 100644 --- a/extensions/web/pkg/command/server.go +++ b/extensions/web/pkg/command/server.go @@ -24,7 +24,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/web/pkg/config/defaults/defaultconfig.go b/extensions/web/pkg/config/defaults/defaultconfig.go index 084bdcfe85..baa74517b0 100644 --- a/extensions/web/pkg/config/defaults/defaultconfig.go +++ b/extensions/web/pkg/config/defaults/defaultconfig.go @@ -8,10 +8,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/web/pkg/config/parser/parse.go b/extensions/web/pkg/config/parser/parse.go index d850943577..c2d8771603 100644 --- a/extensions/web/pkg/config/parser/parse.go +++ b/extensions/web/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +29,9 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/extensions/webdav/pkg/command/health.go b/extensions/webdav/pkg/command/health.go index d6226f8e8f..9882d035bf 100644 --- a/extensions/webdav/pkg/command/health.go +++ b/extensions/webdav/pkg/command/health.go @@ -17,7 +17,11 @@ func Health(cfg *config.Config) *cli.Command { Usage: "check health status", Category: "info", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/webdav/pkg/command/server.go b/extensions/webdav/pkg/command/server.go index 291276cbbe..b603681a0f 100644 --- a/extensions/webdav/pkg/command/server.go +++ b/extensions/webdav/pkg/command/server.go @@ -23,7 +23,11 @@ func Server(cfg *config.Config) *cli.Command { 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) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) diff --git a/extensions/webdav/pkg/config/defaults/defaultconfig.go b/extensions/webdav/pkg/config/defaults/defaultconfig.go index 48e00e17f1..3c975cfa70 100644 --- a/extensions/webdav/pkg/config/defaults/defaultconfig.go +++ b/extensions/webdav/pkg/config/defaults/defaultconfig.go @@ -8,10 +8,8 @@ import ( func FullDefaultConfig() *config.Config { cfg := DefaultConfig() - EnsureDefaults(cfg) Sanitize(cfg) - return cfg } diff --git a/extensions/webdav/pkg/config/parser/parse.go b/extensions/webdav/pkg/config/parser/parse.go index 7597255f9c..be9d202072 100644 --- a/extensions/webdav/pkg/config/parser/parse.go +++ b/extensions/webdav/pkg/config/parser/parse.go @@ -10,7 +10,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/config/envdecode" ) -// ParseConfig loads accounts configuration from known paths. +// ParseConfig loads configuration from known paths. func ParseConfig(cfg *config.Config) error { _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) if err != nil { @@ -29,5 +29,9 @@ func ParseConfig(cfg *config.Config) error { defaults.Sanitize(cfg) + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { return nil } diff --git a/go.mod b/go.mod index 291ea47d4b..346f6127ce 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/blevesearch/bleve_index_api v1.0.1 github.com/coreos/go-oidc/v3 v3.1.0 github.com/cs3org/go-cs3apis v0.0.0-20220412090512-93c5918b4bde - github.com/cs3org/reva/v2 v2.0.0-20220427203355-0164880ac7d3 + github.com/cs3org/reva/v2 v2.0.0-20220502122639-bfbf8690a043 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 diff --git a/go.sum b/go.sum index 1843c2b33a..68f316b32f 100644 --- a/go.sum +++ b/go.sum @@ -318,8 +318,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20220412090512-93c5918b4bde h1:WrD9O8ZaWvsm0 github.com/cs3org/go-cs3apis v0.0.0-20220412090512-93c5918b4bde/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/reva v1.18.0 h1:MbPS5ZAa8RzKcTxAVeSDdISB3XXqLIxqB03BTN5ReBY= github.com/cs3org/reva v1.18.0/go.mod h1:e5VDUDu4vVWIeVkZcW//n6UZzhGGMa+Tz/whCiX3N6o= -github.com/cs3org/reva/v2 v2.0.0-20220427203355-0164880ac7d3 h1:6sKjGI0AUW5tBXWBduaBoc+9sNYZWQR894G0oFCbus0= -github.com/cs3org/reva/v2 v2.0.0-20220427203355-0164880ac7d3/go.mod h1:2e/4HcIy54Mic3V7Ow0bz4n5dkZU0dHIZSWomFe5vng= +github.com/cs3org/reva/v2 v2.0.0-20220502122639-bfbf8690a043 h1:wAvf45pBDnWIN4kpyWpD9uRl9y147ioAXJkfztrMSCM= +github.com/cs3org/reva/v2 v2.0.0-20220502122639-bfbf8690a043/go.mod h1:2e/4HcIy54Mic3V7Ow0bz4n5dkZU0dHIZSWomFe5vng= 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= diff --git a/ocis-pkg/config/config.go b/ocis-pkg/config/config.go index 0bd5b5961e..115d8a0fe4 100644 --- a/ocis-pkg/config/config.go +++ b/ocis-pkg/config/config.go @@ -36,11 +36,6 @@ import ( webdav "github.com/owncloud/ocis/extensions/webdav/pkg/config" ) -// TokenManager is the config for using the reva token manager -type TokenManager struct { - JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET"` -} - const ( // SUPERVISED sets the runtime mode as supervised threads. SUPERVISED = iota @@ -62,22 +57,25 @@ type Runtime struct { type Config struct { *shared.Commons `yaml:"shared"` - Tracing shared.Tracing `yaml:"tracing"` - Log *shared.Log `yaml:"log"` + Tracing *shared.Tracing `yaml:"tracing"` + Log *shared.Log `yaml:"log"` Mode Mode // DEPRECATED File string OcisURL string `yaml:"ocis_url"` - Registry string `yaml:"registry"` - TokenManager TokenManager `yaml:"token_manager"` - Runtime Runtime `yaml:"runtime"` + Registry string `yaml:"registry"` + TokenManager *shared.TokenManager `yaml:"token_manager"` + MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY"` + TransferSecret string `yaml:"transfer_secret" env:"STORAGE_TRANSFER_SECRET"` + MetadataUserID string `yaml:"metadata_user_id"` + Runtime Runtime `yaml:"runtime"` Audit *audit.Config `yaml:"audit"` Accounts *accounts.Config `yaml:"accounts"` GLAuth *glauth.Config `yaml:"glauth"` Graph *graph.Config `yaml:"graph"` - GraphExplorer *graphExplorer.Config `yaml:"graph_explorer"` + GraphExplorer *graphExplorer.Config `yaml:"graph-explorer"` IDP *idp.Config `yaml:"idp"` IDM *idm.Config `yaml:"idm"` Nats *nats.Config `yaml:"nats"` @@ -88,17 +86,17 @@ type Config struct { Settings *settings.Config `yaml:"settings"` Gateway *gateway.Config `yaml:"gateway"` Frontend *frontend.Config `yaml:"frontend"` - AuthBasic *authbasic.Config `yaml:"auth_basic"` - AuthBearer *authbearer.Config `yaml:"auth_bearer"` - AuthMachine *authmachine.Config `yaml:"auth_machine"` + AuthBasic *authbasic.Config `yaml:"auth-basic"` + AuthBearer *authbearer.Config `yaml:"auth-bearer"` + AuthMachine *authmachine.Config `yaml:"auth-machine"` User *user.Config `yaml:"user"` Group *group.Config `yaml:"group"` - AppProvider *appprovider.Config `yaml:"app_provider"` + AppProvider *appprovider.Config `yaml:"appprovider"` Sharing *sharing.Config `yaml:"sharing"` - StorageMetadata *storagemetadata.Config `yaml:"storage_metadata"` - StoragePublicLink *storagepublic.Config `yaml:"storage_public"` - StorageUsers *storageusers.Config `yaml:"storage_users"` - StorageShares *storageshares.Config `yaml:"storage_shares"` + StorageMetadata *storagemetadata.Config `yaml:"storage-metadata"` + StoragePublicLink *storagepublic.Config `yaml:"storage-public"` + StorageUsers *storageusers.Config `yaml:"storage-users"` + StorageShares *storageshares.Config `yaml:"storage-shares"` OCDav *ocdav.Config `yaml:"ocdav"` Store *store.Config `yaml:"store"` Thumbnails *thumbnails.Config `yaml:"thumbnails"` diff --git a/ocis-pkg/config/defaultconfig.go b/ocis-pkg/config/defaultconfig.go index 6b765f1690..8798918bfc 100644 --- a/ocis-pkg/config/defaultconfig.go +++ b/ocis-pkg/config/defaultconfig.go @@ -36,43 +36,40 @@ import ( func DefaultConfig() *Config { return &Config{ - TokenManager: TokenManager{ - JWTSecret: "Pive-Fumkiu4", - }, Runtime: Runtime{ Port: "9250", Host: "localhost", }, - Audit: audit.DefaultConfig(), Accounts: accounts.DefaultConfig(), + AppProvider: appprovider.DefaultConfig(), + Audit: audit.DefaultConfig(), + AuthBasic: authbasic.DefaultConfig(), + AuthBearer: authbearer.DefaultConfig(), + AuthMachine: authmachine.DefaultConfig(), + Frontend: frontend.DefaultConfig(), + Gateway: gateway.DefaultConfig(), GLAuth: glauth.DefaultConfig(), Graph: graph.DefaultConfig(), - IDP: idp.DefaultConfig(), + GraphExplorer: graphExplorer.DefaultConfig(), + Group: group.DefaultConfig(), IDM: idm.DefaultConfig(), + IDP: idp.DefaultConfig(), Nats: nats.DefaultConfig(), Notifications: notifications.DefaultConfig(), - Proxy: proxy.DefaultConfig(), - GraphExplorer: graphExplorer.DefaultConfig(), + OCDav: ocdav.DefaultConfig(), OCS: ocs.DefaultConfig(), + Proxy: proxy.DefaultConfig(), + Search: search.FullDefaultConfig(), Settings: settings.DefaultConfig(), - Web: web.DefaultConfig(), + Sharing: sharing.DefaultConfig(), + StorageMetadata: storagemetadata.DefaultConfig(), + StoragePublicLink: storagepublic.DefaultConfig(), + StorageShares: storageshares.DefaultConfig(), + StorageUsers: storageusers.DefaultConfig(), Store: store.DefaultConfig(), Thumbnails: thumbnails.DefaultConfig(), + User: user.DefaultConfig(), + Web: web.DefaultConfig(), WebDAV: webdav.DefaultConfig(), - Gateway: gateway.FullDefaultConfig(), - AuthBasic: authbasic.FullDefaultConfig(), - AuthBearer: authbearer.FullDefaultConfig(), - AuthMachine: authmachine.FullDefaultConfig(), - User: user.FullDefaultConfig(), - Group: group.FullDefaultConfig(), - Sharing: sharing.FullDefaultConfig(), - StorageMetadata: storagemetadata.FullDefaultConfig(), - StoragePublicLink: storagepublic.FullDefaultConfig(), - StorageUsers: storageusers.FullDefaultConfig(), - StorageShares: storageshares.FullDefaultConfig(), - AppProvider: appprovider.FullDefaultConfig(), - Frontend: frontend.FullDefaultConfig(), - OCDav: ocdav.FullDefaultConfig(), - Search: search.FullDefaultConfig(), } } diff --git a/ocis-pkg/config/parser/parse.go b/ocis-pkg/config/parser/parse.go index ba75a411c0..cd5f8ab32b 100644 --- a/ocis-pkg/config/parser/parse.go +++ b/ocis-pkg/config/parser/parse.go @@ -8,24 +8,16 @@ import ( "github.com/owncloud/ocis/ocis-pkg/shared" ) -// ParseConfig loads ocis configuration. +// ParseConfig loads the ocis configuration and +// copies applicable parts into the commons part, from +// where the extensions can copy it into their own config func ParseConfig(cfg *config.Config) error { _, err := config.BindSourcesToStructs("ocis", 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 = &shared.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 = &shared.Log{} - } + EnsureDefaults(cfg) // load all env variables relevant to the config in the current context. if err := envdecode.Decode(cfg); err != nil { @@ -35,5 +27,95 @@ func ParseConfig(cfg *config.Config) error { } } + EnsureCommons(cfg) + + return Validate(cfg) +} + +// EnsureDefaults, ensures that all pointers in the +// oCIS config (not the extensions configs) are initialized +func EnsureDefaults(cfg *config.Config) { + if cfg.Tracing == nil { + cfg.Tracing = &shared.Tracing{} + } + if cfg.Log == nil { + cfg.Log = &shared.Log{} + } + if cfg.TokenManager == nil { + cfg.TokenManager = &shared.TokenManager{} + } +} + +// EnsureCommons copies applicable parts of the oCIS config into the commons part +func EnsureCommons(cfg *config.Config) { + // ensure the commons part is initialized + if cfg.Commons == nil { + cfg.Commons = &shared.Commons{} + } + + // copy config to the commons part if set + if cfg.Log != nil { + cfg.Commons.Log = &shared.Log{ + Level: cfg.Log.Level, + Pretty: cfg.Log.Pretty, + Color: cfg.Log.Color, + File: cfg.File, + } + } else { + cfg.Commons.Log = &shared.Log{} + } + + // copy tracing to the commons part if set + if cfg.Tracing != nil { + cfg.Commons.Tracing = &shared.Tracing{ + Enabled: cfg.Tracing.Enabled, + Type: cfg.Tracing.Type, + Endpoint: cfg.Tracing.Endpoint, + Collector: cfg.Tracing.Collector, + } + } else { + cfg.Commons.Tracing = &shared.Tracing{} + } + + // copy token manager to the commons part if set + if cfg.TokenManager != nil { + cfg.Commons.TokenManager = cfg.TokenManager + } else { + cfg.Commons.TokenManager = &shared.TokenManager{} + } + + // copy machine auth api key to the commons part if set + if cfg.MachineAuthAPIKey != "" { + cfg.Commons.MachineAuthAPIKey = cfg.MachineAuthAPIKey + } + + // copy transfer secret to the commons part if set + if cfg.TransferSecret != "" { + cfg.Commons.TransferSecret = cfg.TransferSecret + } + + // copy metadata user id to the commons part if set + if cfg.MetadataUserID != "" { + cfg.Commons.MetadataUserID = cfg.MetadataUserID + } +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError("ocis") + } + + if cfg.TransferSecret == "" { + return shared.MissingRevaTransferSecretError("ocis") + } + + if cfg.MachineAuthAPIKey == "" { + return shared.MissingMachineAuthApiKeyError("ocis") + } + + if cfg.MetadataUserID == "" { + return shared.MissingMetadataUserID("ocis") + } + return nil } diff --git a/ocis-pkg/crypto/crypto_suite_test.go b/ocis-pkg/crypto/crypto_suite_test.go index e60462b997..87ac8f6f73 100644 --- a/ocis-pkg/crypto/crypto_suite_test.go +++ b/ocis-pkg/crypto/crypto_suite_test.go @@ -3,7 +3,7 @@ package crypto_test import ( "testing" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/ocis-pkg/crypto/crypto_test.go b/ocis-pkg/crypto/crypto_test.go index 328607ba9e..0f54796255 100644 --- a/ocis-pkg/crypto/crypto_test.go +++ b/ocis-pkg/crypto/crypto_test.go @@ -8,7 +8,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/crypto" "github.com/owncloud/ocis/ocis-pkg/log" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" cfg "github.com/owncloud/ocis/ocis-pkg/config" ) diff --git a/ocis-pkg/generators/password.go b/ocis-pkg/generators/password.go new file mode 100644 index 0000000000..3c2d571fa5 --- /dev/null +++ b/ocis-pkg/generators/password.go @@ -0,0 +1,20 @@ +package generators + +import ( + "crypto/rand" + "math/big" +) + +func GenerateRandomPassword(length int) (string, error) { + const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-=+!@#$%^&*." + ret := make([]byte, length) + for i := 0; i < length; i++ { + num, err := rand.Int(rand.Reader, big.NewInt(int64(len(chars)))) + if err != nil { + return "", err + } + ret[i] = chars[num.Int64()] + } + + return string(ret), nil +} diff --git a/ocis-pkg/shared/errors.go b/ocis-pkg/shared/errors.go new file mode 100644 index 0000000000..de1ed5a825 --- /dev/null +++ b/ocis-pkg/shared/errors.go @@ -0,0 +1,55 @@ +package shared + +import ( + "fmt" + + "github.com/owncloud/ocis/ocis-pkg/config/defaults" +) + +func MissingMachineAuthApiKeyError(service string) error { + return fmt.Errorf("The Machineauth API key has not been configured for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + service, defaults.BaseConfigPath()) +} + +func MissingJWTTokenError(service string) error { + return fmt.Errorf("jwt_secret has not been set properly in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + service, defaults.BaseConfigPath()) +} + +func MissingRevaTransferSecretError(service string) error { + return fmt.Errorf("transfer_secret has not been set properly in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + service, defaults.BaseConfigPath()) +} + +func MissingLDAPBindPassword(service string) error { + return fmt.Errorf("bind_password has not been set properly in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + service, defaults.BaseConfigPath()) +} + +func MissingServiceUserPassword(service, serviceUser string) error { + return fmt.Errorf("password of service user %s has not been set properly in your config for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + serviceUser, service, defaults.BaseConfigPath()) +} + +func MissingMetadataUserID(service string) error { + return fmt.Errorf("The metadata user ID has not been configured for %s. "+ + "Make sure your %s config contains the proper values "+ + "(e.g. by running ocis init or setting it manually in "+ + "the config/corresponding environment variable).", + service, defaults.BaseConfigPath()) +} diff --git a/ocis-pkg/shared/shared_types.go b/ocis-pkg/shared/shared_types.go index 2201bac98d..3497bed611 100644 --- a/ocis-pkg/shared/shared_types.go +++ b/ocis-pkg/shared/shared_types.go @@ -24,10 +24,25 @@ type Tracing struct { Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR"` } +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET" desc:"The secret to mint jwt tokens."` +} + +// Reva defines all available REVA configuration. +type Reva struct { + Address string `yaml:"address" env:"REVA_GATEWAY"` +} + // Commons holds configuration that are common to all extensions. Each extension can then decide whether // to overwrite its values. type Commons struct { - Log *Log `yaml:"log"` - Tracing *Tracing `yaml:"tracing"` - OcisURL string `yaml:"ocis_url" env:"OCIS_URL"` + Log *Log `yaml:"log"` + Tracing *Tracing `yaml:"tracing"` + OcisURL string `yaml:"ocis_url" env:"OCIS_URL"` + TokenManager *TokenManager `yaml:"token_manager"` + Reva *Reva `yaml:"reva"` + MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OCIS_MACHINE_AUTH_API_KEY"` + TransferSecret string `yaml:"transfer_secret,omitempty" env:"REVA_TRANSFER_SECRET"` + MetadataUserID string `yaml:"metadata_user_id" env:"METADATA_USER_ID"` } diff --git a/ocis/pkg/command/accounts.go b/ocis/pkg/command/accounts.go index f8a56bfcc5..e9981b9f54 100644 --- a/ocis/pkg/command/accounts.go +++ b/ocis/pkg/command/accounts.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/accounts/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func AccountsCommand(cfg *config.Config) *cli.Command { Name: cfg.Accounts.Service.Name, Usage: subcommandDescription(cfg.Accounts.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Accounts.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Accounts), } diff --git a/ocis/pkg/command/audit.go b/ocis/pkg/command/audit.go index 638367a166..03d390e632 100644 --- a/ocis/pkg/command/audit.go +++ b/ocis/pkg/command/audit.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/audit/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func AuditCommand(cfg *config.Config) *cli.Command { Name: "audit", Usage: "start audit service", Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Audit.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Audit), } diff --git a/ocis/pkg/command/glauth.go b/ocis/pkg/command/glauth.go index ad91954eb0..8a3059efff 100644 --- a/ocis/pkg/command/glauth.go +++ b/ocis/pkg/command/glauth.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/glauth/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func GLAuthCommand(cfg *config.Config) *cli.Command { Name: cfg.GLAuth.Service.Name, Usage: subcommandDescription(cfg.GLAuth.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.GLAuth.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.GLAuth), } diff --git a/ocis/pkg/command/graph.go b/ocis/pkg/command/graph.go index 836ad44465..89dc41f64c 100644 --- a/ocis/pkg/command/graph.go +++ b/ocis/pkg/command/graph.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/graph/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func GraphCommand(cfg *config.Config) *cli.Command { Name: cfg.Graph.Service.Name, Usage: subcommandDescription(cfg.Graph.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Graph.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Graph), } diff --git a/ocis/pkg/command/graphexplorer.go b/ocis/pkg/command/graphexplorer.go index 95be9e503f..ad33cf7b4a 100644 --- a/ocis/pkg/command/graphexplorer.go +++ b/ocis/pkg/command/graphexplorer.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/graph-explorer/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func GraphExplorerCommand(cfg *config.Config) *cli.Command { Name: cfg.GraphExplorer.Service.Name, Usage: subcommandDescription(cfg.GraphExplorer.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.GraphExplorer.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.GraphExplorer), } diff --git a/ocis/pkg/command/idm.go b/ocis/pkg/command/idm.go index d768b6dc58..9a375c8c68 100644 --- a/ocis/pkg/command/idm.go +++ b/ocis/pkg/command/idm.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/idm/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func IDMCommand(cfg *config.Config) *cli.Command { Name: "idm", Usage: "idm extension commands", Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.IDM.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.IDM), } diff --git a/ocis/pkg/command/idp.go b/ocis/pkg/command/idp.go index 0c6828c592..82909ee9a8 100644 --- a/ocis/pkg/command/idp.go +++ b/ocis/pkg/command/idp.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/idp/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func IDPCommand(cfg *config.Config) *cli.Command { Name: cfg.IDP.Service.Name, Usage: subcommandDescription(cfg.IDP.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.IDP.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.IDP), } diff --git a/ocis/pkg/command/init.go b/ocis/pkg/command/init.go new file mode 100644 index 0000000000..4c697011cc --- /dev/null +++ b/ocis/pkg/command/init.go @@ -0,0 +1,84 @@ +package command + +import ( + "bufio" + "fmt" + "log" + "os" + "strings" + + "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/defaults" + ocisinit "github.com/owncloud/ocis/ocis/pkg/init" + "github.com/owncloud/ocis/ocis/pkg/register" + cli "github.com/urfave/cli/v2" +) + +// InitCommand is the entrypoint for the init command +func InitCommand(cfg *config.Config) *cli.Command { + return &cli.Command{ + Name: "init", + Usage: "initialise an ocis config", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "insecure", + EnvVars: []string{"OCIS_INSECURE"}, + Value: "ask", + Usage: "Allow insecure oCIS config", + }, + &cli.BoolFlag{ + Name: "force-overwrite", + Aliases: []string{"f"}, + EnvVars: []string{"OCIS_FORCE_CONFIG_OVERWRITE"}, + Value: false, + Usage: "Force overwrite existing config file", + }, + &cli.StringFlag{ + Name: "config-path", + Value: defaults.BaseConfigPath(), + Usage: "Config path for the ocis runtime", + EnvVars: []string{"OCIS_CONFIG_DIR"}, + }, + &cli.StringFlag{ + Name: "admin-password", + Aliases: []string{"ap"}, + EnvVars: []string{"ADMIN_PASSWORD", "IDM_ADMIN_PASSWORD"}, + Usage: "Set admin password instead of using a random generated one", + }, + }, + Action: func(c *cli.Context) error { + insecureFlag := c.String("insecure") + insecure := false + if insecureFlag == "ask" { + answer := strings.ToLower(stringPrompt("Do want to configure oCIS with certificate checking disabled?\n This is not recommended for public instances! [yes | no = default]")) + if answer == "yes" || answer == "y" { + insecure = true + } + } else if insecureFlag == strings.ToLower("true") || insecureFlag == strings.ToLower("yes") || insecureFlag == strings.ToLower("y") { + insecure = true + } + err := ocisinit.CreateConfig(insecure, c.Bool("force-overwrite"), c.String("config-path"), c.String("admin-password")) + if err != nil { + log.Fatalf("Could not create config: %s", err) + } + return nil + }, + } +} + +func init() { + register.AddCommand(InitCommand) +} + +func stringPrompt(label string) string { + input := "" + reader := bufio.NewReader(os.Stdin) + for { + fmt.Fprint(os.Stderr, label+" ") + input, _ = reader.ReadString('\n') + if input != "" { + break + } + } + return strings.TrimSpace(input) +} diff --git a/ocis/pkg/command/natsserver.go b/ocis/pkg/command/natsserver.go index 1e7f343231..48cf8174a8 100644 --- a/ocis/pkg/command/natsserver.go +++ b/ocis/pkg/command/natsserver.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/nats/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func NatsServerCommand(cfg *config.Config) *cli.Command { Name: "nats-server", Usage: "start nats server", Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Nats.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Nats), } diff --git a/ocis/pkg/command/notifications.go b/ocis/pkg/command/notifications.go index f4108e299a..ee362dc7ed 100644 --- a/ocis/pkg/command/notifications.go +++ b/ocis/pkg/command/notifications.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/notifications/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func NotificationsCommand(cfg *config.Config) *cli.Command { Name: "notifications", Usage: "start notifications service", Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Notifications.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Notifications), } diff --git a/ocis/pkg/command/ocdav.go b/ocis/pkg/command/ocdav.go index c13e6ee07f..85fdeb4570 100644 --- a/ocis/pkg/command/ocdav.go +++ b/ocis/pkg/command/ocdav.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/ocdav/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,9 +16,14 @@ func OCDavCommand(cfg *config.Config) *cli.Command { Name: "ocdav", Usage: "start ocdav", Category: "extensions", - // Before: func(ctx *cli.Context) error { - // return ParseStorageCommon(ctx, cfg) - // }, + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.OCDav.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.OCDav(cfg.OCDav) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/ocs.go b/ocis/pkg/command/ocs.go index 2fae3beb95..b2f1b5bd62 100644 --- a/ocis/pkg/command/ocs.go +++ b/ocis/pkg/command/ocs.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/ocs/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func OCSCommand(cfg *config.Config) *cli.Command { Name: cfg.OCS.Service.Name, Usage: subcommandDescription(cfg.OCS.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.OCS.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.OCS), } diff --git a/ocis/pkg/command/proxy.go b/ocis/pkg/command/proxy.go index 429ca83e19..219a4c06e1 100644 --- a/ocis/pkg/command/proxy.go +++ b/ocis/pkg/command/proxy.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/proxy/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func ProxyCommand(cfg *config.Config) *cli.Command { Name: cfg.Proxy.Service.Name, Usage: subcommandDescription(cfg.Proxy.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Proxy.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Proxy), } diff --git a/ocis/pkg/command/server.go b/ocis/pkg/command/server.go index 00b9c89da3..c4bba27eb0 100644 --- a/ocis/pkg/command/server.go +++ b/ocis/pkg/command/server.go @@ -1,9 +1,10 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" - "github.com/owncloud/ocis/ocis-pkg/shared" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/owncloud/ocis/ocis/pkg/runtime" "github.com/urfave/cli/v2" @@ -16,14 +17,13 @@ func Server(cfg *config.Config) *cli.Command { Usage: "start a fullstack server (runtime and all extensions in supervised mode)", Category: "fullstack", Before: func(c *cli.Context) error { - return parser.ParseConfig(cfg) + err := parser.ParseConfig(cfg) + if err != nil { + fmt.Printf("%v", err) + } + return err }, Action: func(c *cli.Context) error { - - cfg.Commons = &shared.Commons{ - Log: cfg.Log, - } - r := runtime.New(cfg) return r.Start() }, diff --git a/ocis/pkg/command/settings.go b/ocis/pkg/command/settings.go index 32c8b43e69..1a454bf58c 100644 --- a/ocis/pkg/command/settings.go +++ b/ocis/pkg/command/settings.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/settings/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func SettingsCommand(cfg *config.Config) *cli.Command { Name: cfg.Settings.Service.Name, Usage: subcommandDescription(cfg.Settings.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Settings.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Settings), } diff --git a/ocis/pkg/command/storageappprovider.go b/ocis/pkg/command/storageappprovider.go index beb494d341..f44aa55fad 100644 --- a/ocis/pkg/command/storageappprovider.go +++ b/ocis/pkg/command/storageappprovider.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/appprovider/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageAppProviderCommand(cfg *config.Config) *cli.Command { Name: "storage-app-provider", Usage: "start storage app-provider service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.AppProvider.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.AppProvider(cfg.AppProvider) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storageauthbasic.go b/ocis/pkg/command/storageauthbasic.go index 26164983f7..4c8dba5cdb 100644 --- a/ocis/pkg/command/storageauthbasic.go +++ b/ocis/pkg/command/storageauthbasic.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/auth-basic/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageAuthBasicCommand(cfg *config.Config) *cli.Command { Name: "storage-auth-basic", Usage: "start storage auth-basic service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.AuthBasic.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.AuthBasic(cfg.AuthBasic) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storageauthbearer.go b/ocis/pkg/command/storageauthbearer.go index c3c9855d84..20b641cda4 100644 --- a/ocis/pkg/command/storageauthbearer.go +++ b/ocis/pkg/command/storageauthbearer.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/auth-bearer/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageAuthBearerCommand(cfg *config.Config) *cli.Command { Name: "storage-auth-bearer", Usage: "Start storage auth-bearer service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.AuthBearer.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.AuthBearer(cfg.AuthBearer) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storageauthmachine.go b/ocis/pkg/command/storageauthmachine.go index bbed4b2c1e..f42ecb4b55 100644 --- a/ocis/pkg/command/storageauthmachine.go +++ b/ocis/pkg/command/storageauthmachine.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/auth-machine/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageAuthMachineCommand(cfg *config.Config) *cli.Command { Name: "storage-auth-machine", Usage: "start storage auth-machine service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.AuthMachine.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.AuthMachine(cfg.AuthMachine) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storagefrontend.go b/ocis/pkg/command/storagefrontend.go index 4d37589fee..05252414a9 100644 --- a/ocis/pkg/command/storagefrontend.go +++ b/ocis/pkg/command/storagefrontend.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/frontend/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageFrontendCommand(cfg *config.Config) *cli.Command { Name: "storage-frontend", Usage: "start storage frontend", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Frontend.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.Frontend(cfg.Frontend) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storagegateway.go b/ocis/pkg/command/storagegateway.go index f69adc3053..17047b6068 100644 --- a/ocis/pkg/command/storagegateway.go +++ b/ocis/pkg/command/storagegateway.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/gateway/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,10 +16,14 @@ func StorageGatewayCommand(cfg *config.Config) *cli.Command { Name: "storage-gateway", Usage: "start storage gateway", Category: "extensions", - //Flags: flagset.GatewayWithConfig(cfg.Storage), - // Before: func(ctx *cli.Context) error { - // return ParseStorageCommon(ctx, cfg) - // }, + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Gateway.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.Gateway(cfg.Gateway) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storagegroupprovider.go b/ocis/pkg/command/storagegroupprovider.go index 2e39709ee1..c93de96c11 100644 --- a/ocis/pkg/command/storagegroupprovider.go +++ b/ocis/pkg/command/storagegroupprovider.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/group/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageGroupProviderCommand(cfg *config.Config) *cli.Command { Name: "storage-groupprovider", Usage: "start storage groupprovider service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Group.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.Groups(cfg.Group) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storagemetadata.go b/ocis/pkg/command/storagemetadata.go index 2e87bea4f0..2965c36cfc 100644 --- a/ocis/pkg/command/storagemetadata.go +++ b/ocis/pkg/command/storagemetadata.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/storage-metadata/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageMetadataCommand(cfg *config.Config) *cli.Command { Name: "storage-metadata", Usage: "start storage and data service for metadata", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.StorageMetadata.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.StorageMetadata(cfg.StorageMetadata) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storagepubliclink.go b/ocis/pkg/command/storagepubliclink.go index 06a99d0a7a..fe2f8b75e8 100644 --- a/ocis/pkg/command/storagepubliclink.go +++ b/ocis/pkg/command/storagepubliclink.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/storage-publiclink/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StoragePublicLinkCommand(cfg *config.Config) *cli.Command { Name: "storage-public-link", Usage: "start storage public link storage", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.StoragePublicLink.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.StoragePublicLink(cfg.StoragePublicLink) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storageshares.go b/ocis/pkg/command/storageshares.go index 04fe859bd0..62f13c38a8 100644 --- a/ocis/pkg/command/storageshares.go +++ b/ocis/pkg/command/storageshares.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/storage-shares/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageSharesCommand(cfg *config.Config) *cli.Command { Name: "storage-shares", Usage: "start storage and data provider for shares jail", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.StorageShares.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.StorageShares(cfg.StorageShares) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storagesharing.go b/ocis/pkg/command/storagesharing.go index fe9e3cb796..63c7e2aa06 100644 --- a/ocis/pkg/command/storagesharing.go +++ b/ocis/pkg/command/storagesharing.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/sharing/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageSharingCommand(cfg *config.Config) *cli.Command { Name: "storage-sharing", Usage: "start storage sharing service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Sharing.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.Sharing(cfg.Sharing) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/storageuserprovider.go b/ocis/pkg/command/storageuserprovider.go index dabef25fb0..5e3af09569 100644 --- a/ocis/pkg/command/storageuserprovider.go +++ b/ocis/pkg/command/storageuserprovider.go @@ -1,8 +1,11 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/user/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/config/parser" "github.com/owncloud/ocis/ocis/pkg/register" "github.com/urfave/cli/v2" ) @@ -13,6 +16,14 @@ func StorageUserProviderCommand(cfg *config.Config) *cli.Command { Name: "storage-userprovider", Usage: "start storage userprovider service", Category: "extensions", + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.StorageUsers.Commons = cfg.Commons + return nil + }, Action: func(c *cli.Context) error { origCmd := command.User(cfg.User) return handleOriginalAction(c, origCmd) diff --git a/ocis/pkg/command/store.go b/ocis/pkg/command/store.go index e37d5ab79f..50d1f92cdd 100644 --- a/ocis/pkg/command/store.go +++ b/ocis/pkg/command/store.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/store/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -15,8 +17,13 @@ func StoreCommand(cfg *config.Config) *cli.Command { Name: cfg.Store.Service.Name, Usage: subcommandDescription(cfg.Store.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Store.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Store), } diff --git a/ocis/pkg/command/thumbnails.go b/ocis/pkg/command/thumbnails.go index 8409c98dc0..6b888fb177 100644 --- a/ocis/pkg/command/thumbnails.go +++ b/ocis/pkg/command/thumbnails.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/thumbnails/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func ThumbnailsCommand(cfg *config.Config) *cli.Command { Name: cfg.Thumbnails.Service.Name, Usage: subcommandDescription(cfg.Thumbnails.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Thumbnails.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Thumbnails), } diff --git a/ocis/pkg/command/web.go b/ocis/pkg/command/web.go index 0b3ec822e2..d3e93e4b07 100644 --- a/ocis/pkg/command/web.go +++ b/ocis/pkg/command/web.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/web/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -14,8 +16,13 @@ func WebCommand(cfg *config.Config) *cli.Command { Name: cfg.Web.Service.Name, Usage: subcommandDescription(cfg.Web.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.Web.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.Web), } diff --git a/ocis/pkg/command/webdav.go b/ocis/pkg/command/webdav.go index 7add32497f..693f237d8a 100644 --- a/ocis/pkg/command/webdav.go +++ b/ocis/pkg/command/webdav.go @@ -1,6 +1,8 @@ package command import ( + "fmt" + "github.com/owncloud/ocis/extensions/webdav/pkg/command" "github.com/owncloud/ocis/ocis-pkg/config" "github.com/owncloud/ocis/ocis-pkg/config/parser" @@ -15,8 +17,13 @@ func WebDAVCommand(cfg *config.Config) *cli.Command { Name: cfg.WebDAV.Service.Name, Usage: subcommandDescription(cfg.WebDAV.Service.Name), Category: "extensions", - Before: func(ctx *cli.Context) error { - return parser.ParseConfig(cfg) + Before: func(c *cli.Context) error { + if err := parser.ParseConfig(cfg); err != nil { + fmt.Printf("%v", err) + return err + } + cfg.WebDAV.Commons = cfg.Commons + return nil }, Subcommands: command.GetCommands(cfg.WebDAV), } diff --git a/ocis/pkg/init/init.go b/ocis/pkg/init/init.go new file mode 100644 index 0000000000..4f8bf8a51a --- /dev/null +++ b/ocis/pkg/init/init.go @@ -0,0 +1,312 @@ +package init + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path" + "time" + + "github.com/gofrs/uuid" + "github.com/owncloud/ocis/ocis-pkg/generators" + "gopkg.in/yaml.v2" +) + +const configFilename string = "ocis.yaml" // TODO: use also a constant for reading this file +const passwordLength int = 32 + +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret"` +} + +type InsecureExtension struct { + Insecure bool +} + +type InsecureProxyExtension struct { + Insecure_backends bool +} + +type DataProviderInsecureSettings struct { + Data_provider_insecure bool +} + +type LdapSettings struct { + Bind_password string +} +type LdapBasedExtension struct { + Ldap LdapSettings +} + +type GraphExtension struct { + Spaces InsecureExtension + Identity LdapBasedExtension +} + +type ServiceUserPasswordsSettings struct { + AdminPassword string `yaml:"admin_password"` + IdmPassword string `yaml:"idm_password"` + RevaPassword string `yaml:"reva_password"` + IdpPassword string `yaml:"idp_password"` +} +type IdmExtension struct { + ServiceUserPasswords ServiceUserPasswordsSettings `yaml:"service_user_passwords"` +} + +type FrontendExtension struct { + Archiver InsecureExtension + AppProvider InsecureExtension `yaml:"app_provider"` +} + +type AuthbasicExtension struct { + AuthProviders LdapBasedExtension `yaml:"auth_providers"` +} + +type AuthProviderSettings struct { + Oidc InsecureExtension +} +type AuthbearerExtension struct { + AuthProviders AuthProviderSettings `yaml:"auth_providers"` +} + +type UserAndGroupExtension struct { + Drivers LdapBasedExtension +} + +type ThumbnailSettings struct { + WebdavAllowInsecure bool `yaml:"webdav_allow_insecure"` + Cs3AllowInsecure bool `yaml:"cs3_allow_insecure"` +} + +type ThumbNailExtension struct { + Thumbnail ThumbnailSettings +} + +// TODO: use the oCIS config struct instead of this custom struct +// We can't use it right now, because it would need "omitempty" on +// all elements, in order to produce a slim config file with `ocis init`. +// We can't just add these "omitempty" tags, since we want to generate +// full example configuration files with that struct, too. +// Proposed solution to get rid of this temporary solution: +// - use the oCIS config struct +// - set the needed values like below +// - marshal it to yaml +// - unmarshal it into yaml.Node +// - recurse through the nodes and delete empty / default ones +// - marshal it to yaml +type OcisConfig struct { + TokenManager TokenManager `yaml:"token_manager"` + MachineAuthApiKey string `yaml:"machine_auth_api_key"` + TransferSecret string `yaml:"transfer_secret"` + MetadataUserID string `yaml:"metadata_user_id"` + Graph GraphExtension + Idp LdapBasedExtension + Idm IdmExtension + Proxy InsecureProxyExtension + Frontend FrontendExtension + AuthBasic AuthbasicExtension `yaml:"auth-basic"` + AuthBearer AuthbearerExtension `yaml:"auth-bearer"` + User UserAndGroupExtension + Group UserAndGroupExtension + StorageMetadata DataProviderInsecureSettings `yaml:"storage-metadata"` + StorageUsers DataProviderInsecureSettings `yaml:"storage-users"` + Ocdav InsecureExtension + Thumbnails ThumbNailExtension +} + +func checkConfigPath(configPath string) error { + targetPath := path.Join(configPath, configFilename) + if _, err := os.Stat(targetPath); err == nil { + return fmt.Errorf("config in %s already exists", targetPath) + } + return nil +} + +func backupOcisConfigFile(configPath string) (string, error) { + sourceConfig := path.Join(configPath, configFilename) + targetBackupConfig := path.Join(configPath, configFilename+"."+time.Now().Format("2006-01-02-15-04-05")+".backup") + source, err := os.Open(sourceConfig) + if err != nil { + log.Fatalf("Could not read %s (%s)", sourceConfig, err) + } + defer source.Close() + target, err := os.Create(targetBackupConfig) + if err != nil { + log.Fatalf("Could not generate backup %s (%s)", targetBackupConfig, err) + } + defer target.Close() + _, err = io.Copy(target, source) + if err != nil { + log.Fatalf("Could not write backup %s (%s)", targetBackupConfig, err) + } + return targetBackupConfig, nil +} + +// CreateConfig creates a config file with random passwords at configPath +func CreateConfig(insecure, forceOverwrite bool, configPath, adminPassword string) error { + err := checkConfigPath(configPath) + if err != nil && !forceOverwrite { + return err + } + targetBackupConfig := "" + if err != nil { + targetBackupConfig, err = backupOcisConfigFile(configPath) + if err != nil { + return err + } + } + err = os.MkdirAll(configPath, 0700) + if err != nil { + return err + } + + metadataUserID := uuid.Must(uuid.NewV4()).String() + + idmServicePassword, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for idm: %s", err) + } + idpServicePassword, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for idp: %s", err) + } + ocisAdminServicePassword := adminPassword + if ocisAdminServicePassword == "" { + ocisAdminServicePassword, err = generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for ocis admin: %s", err) + } + } + + revaServicePassword, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for reva: %s", err) + } + tokenManagerJwtSecret, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for tokenmanager: %s", err) + } + machineAuthApiKey, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for machineauthsecret: %s", err) + } + revaTransferSecret, err := generators.GenerateRandomPassword(passwordLength) + if err != nil { + return fmt.Errorf("could not generate random password for machineauthsecret: %s", err) + } + + cfg := OcisConfig{ + TokenManager: TokenManager{ + JWTSecret: tokenManagerJwtSecret, + }, + MachineAuthApiKey: machineAuthApiKey, + TransferSecret: revaTransferSecret, + MetadataUserID: metadataUserID, + Idm: IdmExtension{ + ServiceUserPasswords: ServiceUserPasswordsSettings{ + AdminPassword: ocisAdminServicePassword, + IdpPassword: idpServicePassword, + RevaPassword: revaServicePassword, + IdmPassword: idmServicePassword, + }, + }, + Idp: LdapBasedExtension{ + Ldap: LdapSettings{ + Bind_password: idpServicePassword, + }, + }, + AuthBasic: AuthbasicExtension{ + AuthProviders: LdapBasedExtension{ + Ldap: LdapSettings{ + Bind_password: revaServicePassword, + }, + }, + }, + Group: UserAndGroupExtension{ + Drivers: LdapBasedExtension{ + Ldap: LdapSettings{ + Bind_password: revaServicePassword, + }, + }, + }, + User: UserAndGroupExtension{ + Drivers: LdapBasedExtension{ + Ldap: LdapSettings{ + Bind_password: revaServicePassword, + }, + }, + }, + Graph: GraphExtension{ + Identity: LdapBasedExtension{ + Ldap: LdapSettings{ + Bind_password: idmServicePassword, + }, + }, + }, + } + + if insecure { + cfg.AuthBearer = AuthbearerExtension{ + AuthProviders: AuthProviderSettings{ + Oidc: InsecureExtension{ + Insecure: true, + }, + }, + } + cfg.Frontend = FrontendExtension{ + AppProvider: InsecureExtension{ + Insecure: true, + }, + Archiver: InsecureExtension{ + Insecure: true, + }, + } + cfg.Graph.Spaces = InsecureExtension{ + Insecure: true, + } + cfg.Ocdav = InsecureExtension{ + Insecure: true, + } + cfg.Proxy = InsecureProxyExtension{ + Insecure_backends: true, + } + cfg.StorageMetadata = DataProviderInsecureSettings{ + Data_provider_insecure: true, + } + cfg.StorageUsers = DataProviderInsecureSettings{ + Data_provider_insecure: true, + } + cfg.Thumbnails = ThumbNailExtension{ + Thumbnail: ThumbnailSettings{ + WebdavAllowInsecure: true, + Cs3AllowInsecure: true, + }, + } + } + + yamlOutput, err := yaml.Marshal(cfg) + if err != nil { + return fmt.Errorf("could not marshall config into yaml: %s", err) + } + targetPath := path.Join(configPath, configFilename) + err = ioutil.WriteFile(targetPath, yamlOutput, 0600) + if err != nil { + return err + } + fmt.Printf( + "\n=========================================\n"+ + " generated OCIS Config\n"+ + "=========================================\n"+ + " configpath : %s\n"+ + " user : admin\n"+ + " password : %s\n\n", + targetPath, ocisAdminServicePassword) + if targetBackupConfig != "" { + fmt.Printf("\n=========================================\n"+ + "An older config file has been backuped to\n %s\n\n", + targetBackupConfig) + } + return nil +} diff --git a/ocis/pkg/runtime/service/service.go b/ocis/pkg/runtime/service/service.go index 72f763acdb..99f947155b 100644 --- a/ocis/pkg/runtime/service/service.go +++ b/ocis/pkg/runtime/service/service.go @@ -107,38 +107,38 @@ func NewService(options ...Option) (*Service, error) { cfg: opts.Config, } - s.ServicesRegistry["settings"] = settings.NewSutureService - s.ServicesRegistry["nats"] = nats.NewSutureService - s.ServicesRegistry["storage-metadata"] = storagemetadata.NewStorageMetadata - s.ServicesRegistry["glauth"] = glauth.NewSutureService - s.ServicesRegistry["graph"] = graph.NewSutureService - s.ServicesRegistry["graph-explorer"] = graphExplorer.NewSutureService - s.ServicesRegistry["idm"] = idm.NewSutureService - s.ServicesRegistry["ocs"] = ocs.NewSutureService - s.ServicesRegistry["store"] = store.NewSutureService - s.ServicesRegistry["thumbnails"] = thumbnails.NewSutureService - s.ServicesRegistry["web"] = web.NewSutureService - s.ServicesRegistry["webdav"] = webdav.NewSutureService - s.ServicesRegistry["storage-frontend"] = frontend.NewFrontend - s.ServicesRegistry["ocdav"] = ocdav.NewOCDav - s.ServicesRegistry["storage-gateway"] = gateway.NewGateway - s.ServicesRegistry["storage-userprovider"] = user.NewUserProvider - s.ServicesRegistry["storage-groupprovider"] = group.NewGroupProvider - s.ServicesRegistry["storage-authbasic"] = authbasic.NewAuthBasic - s.ServicesRegistry["storage-authbearer"] = authbearer.NewAuthBearer - s.ServicesRegistry["storage-authmachine"] = authmachine.NewAuthMachine - s.ServicesRegistry["storage-users"] = storageusers.NewStorageUsers - s.ServicesRegistry["storage-shares"] = storageshares.NewStorageShares - s.ServicesRegistry["storage-public-link"] = storagepublic.NewStoragePublicLink - s.ServicesRegistry["storage-appprovider"] = appprovider.NewAppProvider - s.ServicesRegistry["notifications"] = notifications.NewSutureService - s.ServicesRegistry["search"] = search.NewSutureService + s.ServicesRegistry[opts.Config.Settings.Service.Name] = settings.NewSutureService + s.ServicesRegistry[opts.Config.Nats.Service.Name] = nats.NewSutureService + s.ServicesRegistry[opts.Config.StorageMetadata.Service.Name] = storagemetadata.NewStorageMetadata + s.ServicesRegistry[opts.Config.GLAuth.Service.Name] = glauth.NewSutureService + s.ServicesRegistry[opts.Config.Graph.Service.Name] = graph.NewSutureService + s.ServicesRegistry[opts.Config.GraphExplorer.Service.Name] = graphExplorer.NewSutureService + s.ServicesRegistry[opts.Config.IDM.Service.Name] = idm.NewSutureService + s.ServicesRegistry[opts.Config.OCS.Service.Name] = ocs.NewSutureService + s.ServicesRegistry[opts.Config.Store.Service.Name] = store.NewSutureService + s.ServicesRegistry[opts.Config.Thumbnails.Service.Name] = thumbnails.NewSutureService + s.ServicesRegistry[opts.Config.Web.Service.Name] = web.NewSutureService + s.ServicesRegistry[opts.Config.WebDAV.Service.Name] = webdav.NewSutureService + s.ServicesRegistry[opts.Config.Frontend.Service.Name] = frontend.NewFrontend + s.ServicesRegistry[opts.Config.OCDav.Service.Name] = ocdav.NewOCDav + s.ServicesRegistry[opts.Config.Gateway.Service.Name] = gateway.NewGateway + s.ServicesRegistry[opts.Config.User.Service.Name] = user.NewUserProvider + s.ServicesRegistry[opts.Config.Group.Service.Name] = group.NewGroupProvider + s.ServicesRegistry[opts.Config.AuthBasic.Service.Name] = authbasic.NewAuthBasic + s.ServicesRegistry[opts.Config.AuthBearer.Service.Name] = authbearer.NewAuthBearer + s.ServicesRegistry[opts.Config.AuthMachine.Service.Name] = authmachine.NewAuthMachine + s.ServicesRegistry[opts.Config.StorageUsers.Service.Name] = storageusers.NewStorageUsers + s.ServicesRegistry[opts.Config.StorageShares.Service.Name] = storageshares.NewStorageShares + s.ServicesRegistry[opts.Config.StoragePublicLink.Service.Name] = storagepublic.NewStoragePublicLink + s.ServicesRegistry[opts.Config.AppProvider.Service.Name] = appprovider.NewAppProvider + s.ServicesRegistry[opts.Config.Notifications.Service.Name] = notifications.NewSutureService + s.ServicesRegistry[opts.Config.Search.Service.Name] = search.NewSutureService // populate delayed services - s.Delayed["storage-sharing"] = sharing.NewSharing - s.Delayed["accounts"] = accounts.NewSutureService - s.Delayed["proxy"] = proxy.NewSutureService - s.Delayed["idp"] = idp.NewSutureService + s.Delayed[opts.Config.Sharing.Service.Name] = sharing.NewSharing + s.Delayed[opts.Config.Accounts.Service.Name] = accounts.NewSutureService + s.Delayed[opts.Config.Proxy.Service.Name] = proxy.NewSutureService + s.Delayed[opts.Config.IDP.Service.Name] = idp.NewSutureService return s, nil } diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md index 727e90677d..87bdf5ad1b 100644 --- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md @@ -1798,7 +1798,7 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [Incorrect response while listing resources of a folder with depth infinity](https://github.com/owncloud/ocis/issues/3073) -- [apiWebdavOperations/listFiles.feature:180](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L180) +- [apiWebdavOperations/listFiles.feature:182](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L182) ### [[spaces webdav] upload to a share that was locked by owner ends with status code 409](https://github.com/owncloud/ocis/issues/3128) @@ -1815,9 +1815,9 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [can't access public link resources with spaces webdav API](https://github.com/owncloud/ocis/issues/3085) -- [apiWebdavOperations/listFiles.feature:216](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L216) -- [apiWebdavOperations/listFiles.feature:254](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L254) -- [apiWebdavOperations/listFiles.feature:291](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L291) +- [apiWebdavOperations/listFiles.feature:218](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L218) +- [apiWebdavOperations/listFiles.feature:256](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L256) +- [apiWebdavOperations/listFiles.feature:294](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L294) #### [OCS response is not returned when a disabled user tries to enable himself](https://github.com/owncloud/ocis/issues/3254) @@ -1847,10 +1847,6 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [OCS status code zero](https://github.com/owncloud/ocis/issues/3621) - [apiShareManagementToShares/moveReceivedShare.feature:32](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/moveReceivedShare.feature#L32) -#### [share_with_user_type is not set in response](https://github.com/owncloud/ocis/issues/3622) -- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:37](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L37) -- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:38](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L38) - #### [HTTP status code differ while listing the contents of another user's trash bin](https://github.com/owncloud/ocis/issues/3561) - [apiTrashbin/trashbinFilesFolders.feature:199](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L199) - [apiTrashbin/trashbinFilesFolders.feature:223](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L223) @@ -1859,5 +1855,32 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [HTTP status code differ while deleting file of another user's trash bin](https://github.com/owncloud/ocis/issues/3544) - [apiTrashbin/trashbinDelete.feature:108](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L108) +#### [Problem accessing trashbin with personal space id](https://github.com/owncloud/ocis/issues/3639) +- [apiTrashbin/trashbinDelete.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L35) +- [apiTrashbin/trashbinDelete.feature:36](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L36) +- [apiTrashbin/trashbinDelete.feature:58](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L58) +- [apiTrashbin/trashbinDelete.feature:85](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L85) +- [apiTrashbin/trashbinDelete.feature:130](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L130) +- [apiTrashbin/trashbinDelete.feature:152](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L152) +- [apiTrashbin/trashbinDelete.feature:177](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L177) +- [apiTrashbin/trashbinDelete.feature:202](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L202) +- [apiTrashbin/trashbinDelete.feature:239](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L239) +- [apiTrashbin/trashbinDelete.feature:276](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L276) +- [apiTrashbin/trashbinDelete.feature:324](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L324) +- [apiTrashbin/trashbinFilesFolders.feature:25](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L25) +- [apiTrashbin/trashbinFilesFolders.feature:41](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L41) +- [apiTrashbin/trashbinFilesFolders.feature:59](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L59) +- [apiTrashbin/trashbinFilesFolders.feature:80](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L80) +- [apiTrashbin/trashbinFilesFolders.feature:99](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L99) +- [apiTrashbin/trashbinFilesFolders.feature:135](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L135) +- [apiTrashbin/trashbinFilesFolders.feature:158](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L158) +- [apiTrashbin/trashbinFilesFolders.feature:313](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L313) +- [apiTrashbin/trashbinFilesFolders.feature:314](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L314) +- [apiTrashbin/trashbinFilesFolders.feature:315](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L315) +- [apiTrashbin/trashbinFilesFolders.feature:334](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L334) +- [apiTrashbin/trashbinFilesFolders.feature:354](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L354) +- [apiTrashbin/trashbinFilesFolders.feature:408](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L408) +- [apiTrashbin/trashbinFilesFolders.feature:445](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L445) + Note: always have an empty line at the end of this file. The bash script that processes this file requires that the last line has a newline on the end. diff --git a/tests/acceptance/expected-failures-graphAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-graphAPI-on-OCIS-storage.md index 6c74246fe0..f513a93f0a 100644 --- a/tests/acceptance/expected-failures-graphAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-graphAPI-on-OCIS-storage.md @@ -1579,7 +1579,7 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [Incorrect response while listing resources of a folder with depth infinity](https://github.com/owncloud/ocis/issues/3073) -- [apiWebdavOperations/listFiles.feature:180](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L180) +- [apiWebdavOperations/listFiles.feature:182](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L182) ### [[spaces webdav] upload to a share that was locked by owner ends with status code 409](https://github.com/owncloud/ocis/issues/3128) @@ -1596,9 +1596,9 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [can't access public link resources with spaces webdav API](https://github.com/owncloud/ocis/issues/3085) -- [apiWebdavOperations/listFiles.feature:216](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L216) -- [apiWebdavOperations/listFiles.feature:254](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L254) -- [apiWebdavOperations/listFiles.feature:291](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L291) +- [apiWebdavOperations/listFiles.feature:218](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L218) +- [apiWebdavOperations/listFiles.feature:256](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L256) +- [apiWebdavOperations/listFiles.feature:294](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/listFiles.feature#L294) #### [Trying to modify a shared file using spaces end-point returns 409 HTTP status code](https://github.com/owncloud/ocis/issues/3241) @@ -1639,10 +1639,6 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [OCS status code zero](https://github.com/owncloud/ocis/issues/3621) - [apiShareManagementToShares/moveReceivedShare.feature:32](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/moveReceivedShare.feature#L32) -#### [share_with_user_type is not set in response](https://github.com/owncloud/ocis/issues/3622) -- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:37](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L37) -- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:38](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L38) - #### [HTTP status code differ while listing the contents of another user's trash bin](https://github.com/owncloud/ocis/issues/3561) - [apiTrashbin/trashbinFilesFolders.feature:199](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L199) - [apiTrashbin/trashbinFilesFolders.feature:223](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L223) @@ -1651,5 +1647,32 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [HTTP status code differ while deleting file of another user's trash bin](https://github.com/owncloud/ocis/issues/3544) - [apiTrashbin/trashbinDelete.feature:108](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L108) +#### [Problem accessing trashbin with personal space id](https://github.com/owncloud/ocis/issues/3639) +- [apiTrashbin/trashbinDelete.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L35) +- [apiTrashbin/trashbinDelete.feature:36](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L36) +- [apiTrashbin/trashbinDelete.feature:58](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L58) +- [apiTrashbin/trashbinDelete.feature:85](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L85) +- [apiTrashbin/trashbinDelete.feature:130](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L130) +- [apiTrashbin/trashbinDelete.feature:152](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L152) +- [apiTrashbin/trashbinDelete.feature:177](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L177) +- [apiTrashbin/trashbinDelete.feature:202](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L202) +- [apiTrashbin/trashbinDelete.feature:239](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L239) +- [apiTrashbin/trashbinDelete.feature:276](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L276) +- [apiTrashbin/trashbinDelete.feature:324](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinDelete.feature#L324) +- [apiTrashbin/trashbinFilesFolders.feature:25](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L25) +- [apiTrashbin/trashbinFilesFolders.feature:41](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L41) +- [apiTrashbin/trashbinFilesFolders.feature:59](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L59) +- [apiTrashbin/trashbinFilesFolders.feature:80](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L80) +- [apiTrashbin/trashbinFilesFolders.feature:99](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L99) +- [apiTrashbin/trashbinFilesFolders.feature:135](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L135) +- [apiTrashbin/trashbinFilesFolders.feature:158](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L158) +- [apiTrashbin/trashbinFilesFolders.feature:313](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L313) +- [apiTrashbin/trashbinFilesFolders.feature:314](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L314) +- [apiTrashbin/trashbinFilesFolders.feature:315](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L315) +- [apiTrashbin/trashbinFilesFolders.feature:334](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L334) +- [apiTrashbin/trashbinFilesFolders.feature:354](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L354) +- [apiTrashbin/trashbinFilesFolders.feature:408](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L408) +- [apiTrashbin/trashbinFilesFolders.feature:445](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiTrashbin/trashbinFilesFolders.feature#L445) + Note: always have an empty line at the end of this file. The bash script that processes this file requires that the last line has a newline on the end. diff --git a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md index b3a2909b07..e4b315e64d 100644 --- a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md @@ -472,3 +472,6 @@ Other free text and markdown formatting can be used elsewhere in the document if ### [publicLinkCreate.feature:172 is failing](https://github.com/owncloud/ocis/issues/3581) - [webUISharingPublicBasic/publicLinkCreate.feature:172](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingPublicBasic/publicLinkCreate.feature#172) + +### [Creating group with problematic group name via graph api gives 500 error](https://github.com/owncloud/ocis/issues/3631) +- [webUISharingInternalGroupsEdgeCases/shareWithGroupsEdgeCases.feature:41](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingInternalGroupsEdgeCases/shareWithGroupsEdgeCases.feature:41) diff --git a/tests/acceptance/features/bootstrap/SpacesContext.php b/tests/acceptance/features/bootstrap/SpacesContext.php index 61d8f20b0d..5f9c23357d 100644 --- a/tests/acceptance/features/bootstrap/SpacesContext.php +++ b/tests/acceptance/features/bootstrap/SpacesContext.php @@ -220,6 +220,24 @@ class SpacesContext implements Context { return $spaces[$spaceName]; } + /** + * The method finds available spaces to the manager user and returns the space by spaceName + * + * @param string $user + * @param string $spaceName + * + * @return array + */ + public function getSpaceByNameManager(string $user, string $spaceName): array { + $this->theUserListsAllAvailableSpacesUsingTheGraphApi($user); + + $spaces = $this->getAvailableSpaces(); + Assert::assertIsArray($spaces[$spaceName], "Space with name $spaceName for user $user not found"); + Assert::assertNotEmpty($spaces[$spaceName]["root"]["webDavUrl"], "WebDavUrl for space with name $spaceName for user $user not found"); + + return $spaces[$spaceName]; + } + /** * The method finds file by fileName and spaceName and returns data of file wich contains in responseHeader * fileName contains the path, if the file is in the folder @@ -349,7 +367,7 @@ class SpacesContext implements Context { /** * The method first disables and then deletes spaces * @param string $driveType - * + * * @return void * * @throws Exception @@ -410,6 +428,33 @@ class SpacesContext implements Context { return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body); } + /** + * Send Graph List All Spaces Request + * + * @param string $user + * @param string $password + * @param string $urlArguments + * @param string $xRequestId + * @param array $body + * @param array $headers + * + * @return ResponseInterface + * + * @throws GuzzleException + */ + public function listAllSpacesRequest( + string $user, + string $password, + string $urlArguments = '', + string $xRequestId = '', + array $body = [], + array $headers = [] + ): ResponseInterface { + $fullUrl = $this->baseUrl . "/graph/v1.0/drives/" . $urlArguments; + + return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body); + } + /** * Send Graph List Single Space Request * @@ -530,6 +575,24 @@ class SpacesContext implements Context { $this->rememberTheAvailableSpaces(); } + /** + * + * @param string $user + * + * @return void + * + * @throws GuzzleException + */ + public function theUserListsAllAvailableSpacesUsingTheGraphApi(string $user): void { + $this->featureContext->setResponse( + $this->listAllSpacesRequest( + $user, + $this->featureContext->getPasswordForUser($user) + ) + ); + $this->rememberTheAvailableSpaces(); + } + /** * @When /^user "([^"]*)" lists all available spaces via the GraphApi with query "([^"]*)"$/ * @@ -1145,7 +1208,7 @@ class SpacesContext implements Context { $results = []; if ($multistatusResults !== null) { foreach ($multistatusResults as $multistatusResult) { - $entryPath = $multistatusResult['value'][0]['value']; + $entryPath = \urldecode($multistatusResult['value'][0]['value']); $entryName = \str_replace($topWebDavPath, "", $entryPath); $entryName = \rawurldecode($entryName); $entryName = \trim($entryName, "/"); @@ -1951,7 +2014,7 @@ class SpacesContext implements Context { string $userWithManagerRights = '' ): void { if (!empty($userWithManagerRights)) { - $space = $this->getSpaceByName($userWithManagerRights, $spaceName); + $space = $this->getSpaceByNameManager($userWithManagerRights, $spaceName); } else { $space = $this->getSpaceByName($user, $spaceName); }