Skip to content

Commit 2400b40

Browse files
committed
devtools: add deployment for multi-tenancy
1 parent b5b15f2 commit 2400b40

32 files changed

+3663
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
## Basic Settings ##
2+
# Define the docker compose log driver used.
3+
# Defaults to local
4+
LOG_DRIVER=
5+
# If you're on an internet facing server, comment out following line.
6+
# It skips certificate validation for various parts of OpenCloud and is
7+
# needed when self signed certificates are used.
8+
INSECURE=true
9+
10+
## Features ##
11+
COMPOSE_FILE=docker-compose.yml:traefik.yml:keycloak.yml:ldap-server.yml
12+
13+
## Traefik Settings ##
14+
# Note: Traefik is always enabled and can't be disabled.
15+
# Serve Traefik dashboard.
16+
# Defaults to "false".
17+
TRAEFIK_DASHBOARD=
18+
# Domain of Traefik, where you can find the dashboard.
19+
# Defaults to "traefik.opencloud.test"
20+
TRAEFIK_DOMAIN=
21+
# Basic authentication for the traefik dashboard.
22+
# Defaults to user "admin" and password "admin" (written as: "admin:$2y$05$KDHu3xq92SPaO3G8Ybkc7edd51pPLJcG1nWk3lmlrIdANQ/B6r5pq").
23+
# To create user:password pair, it's possible to use this command:
24+
# echo $(htpasswd -nB user) | sed -e s/\\$/\\$\\$/g
25+
TRAEFIK_BASIC_AUTH_USERS=
26+
# Email address for obtaining LetsEncrypt certificates.
27+
# Needs only be changed if this is a public facing server.
28+
TRAEFIK_ACME_MAIL=
29+
# Set to the following for testing to check the certificate process:
30+
# "https://acme-staging-v02.api.letsencrypt.org/directory"
31+
# With staging configured, there will be an SSL error in the browser.
32+
# When certificates are displayed and are emitted by # "Fake LE Intermediate X1",
33+
# the process went well and the envvar can be reset to empty to get valid certificates.
34+
TRAEFIK_ACME_CASERVER=
35+
# Enable the Traefik ACME (Automatic Certificate Management Environment) for automatic SSL certificate management.
36+
TRAEFIK_SERVICES_TLS_CONFIG="tls.certresolver=letsencrypt"
37+
# Enable Traefik to use local certificates.
38+
#TRAEFIK_SERVICES_TLS_CONFIG="tls=true"
39+
# You also need to provide a config file in ./config/traefik/dynamic/certs.yml
40+
# Example:
41+
# cat ./config/traefik/dynamic/certs.yml
42+
# tls:
43+
# certificates:
44+
# - certFile: /certs/opencloud.test.crt
45+
# keyFile: /certs/opencloud.test.key
46+
# stores:
47+
# - default
48+
#
49+
# The certificates need to copied into ./certs/, the absolute path inside the container is /certs/.
50+
# You can also use TRAEFIK_CERTS_DIR=/path/on/host to set the path to the certificates directory.
51+
# Enable the access log for Traefik by setting the following variable to true.
52+
TRAEFIK_ACCESS_LOG=
53+
# Configure the log level for Traefik.
54+
# Possible values are "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" and "PANIC". Default is "ERROR".
55+
TRAEFIK_LOG_LEVEL=
56+
57+
58+
## OpenCloud Settings ##
59+
# The opencloud container image.
60+
# For production releases: "opencloudeu/opencloud"
61+
# For rolling releases: "opencloudeu/opencloud-rolling"
62+
# Defaults to production if not set otherwise
63+
OC_DOCKER_IMAGE=opencloudeu/opencloud-rolling
64+
# The openCloud container version.
65+
# Defaults to "latest" and points to the latest stable tag.
66+
OC_DOCKER_TAG=
67+
# Domain of openCloud, where you can find the frontend.
68+
# Defaults to "cloud.opencloud.test"
69+
OC_DOMAIN=
70+
# Demo users should not be created on a production instance,
71+
# because their passwords are public. Defaults to "false".
72+
# If demo users is set to "true", the following user accounts are created automatically:
73+
# alan, mary, margaret, dennis and lynn - the password is 'demo' for all.
74+
DEMO_USERS=
75+
# Admin Password for the OpenCloud admin user.
76+
# NOTE: This is only needed when using the built-in LDAP server (idm).
77+
# If you are using an external LDAP server, the admin password is managed by the LDAP server.
78+
# NOTE: This variable needs to be set before the first start of OpenCloud. Changes to this variable after the first start will be IGNORED.
79+
# If not set, opencloud will not work properly. The container will be restarting.
80+
# After the first initialization, the admin password can only be changed via the OpenCloud User Settings UI or by using the OpenCloud CLI.
81+
# Documentation: https://docs.opencloud.eu/docs/admin/resources/common-issues#-change-admin-password-set-in-env
82+
INITIAL_ADMIN_PASSWORD=
83+
# Define the openCloud loglevel used.
84+
#
85+
LOG_LEVEL=
86+
# Define the kind of logging.
87+
# The default log can be read by machines.
88+
# Set this to true to make the log human readable.
89+
# LOG_PRETTY=true
90+
#
91+
# Define the openCloud storage location. Set the paths for config and data to a local path.
92+
# Ensure that the configuration and data directories are owned by the user and group with ID 1000:1000.
93+
# This matches the default user inside the container and avoids permission issues when accessing files.
94+
# Note that especially the data directory can grow big.
95+
# Leaving it default stores data in docker internal volumes.
96+
# OC_CONFIG_DIR=/your/local/opencloud/config
97+
# OC_DATA_DIR=/your/local/opencloud/data
98+
99+
### Compose Configuration ###
100+
# Path separator for supplemental compose files specified in COMPOSE_FILE.
101+
COMPOSE_PATH_SEPARATOR=:
102+
103+
### Ldap Settings ###
104+
# LDAP is always needed for OpenCloud to store user data as there is no relational database.
105+
# The built-in LDAP server should used for testing purposes or small installations only.
106+
# For production installations, it is recommended to use an external LDAP server.
107+
# We are using OpenLDAP as the default LDAP server because it is proven to be stable and reliable.
108+
# This LDAP configuration is known to work with OpenCloud and provides a blueprint for
109+
# configuring an external LDAP server based on other products like Microsoft Active Directory or other LDAP servers.
110+
#
111+
# Password of LDAP bind user "cn=admin,dc=opencloud,dc=eu". Defaults to "admin"
112+
LDAP_BIND_PASSWORD=
113+
# The LDAP server also creates an openCloud admin user dn: uid=admin,ou=users,dc=opencloud,dc=eu
114+
# The initial password for this user is "admin"
115+
# NOTE: This password can only be set once, if you want to change it later, you have to use the OpenCloud User Settings UI.
116+
# If you changed the password and lost it, you need to execute the following LDAP query to reset it:
117+
# enter the ldap-server container with `docker compose exec ldap-server sh`
118+
# and run the following command to change the password:
119+
# ldappasswd -H ldap://127.0.0.1:1389 -D "cn=admin,dc=opencloud,dc=eu" -W "uid=admin,ou=users,dc=opencloud,dc=eu"
120+
# You will be prompted for the LDAP bind password.
121+
# The output should provide you a new password for the admin user.
122+
123+
124+
### Keycloak Settings ###
125+
# Keycloak is an open-source identity and access management solution.
126+
# We are using Keycloak as the default identity provider on production installations.
127+
# It can be used to federate authentication with other identity providers like
128+
# Microsoft Entra ID, ADFS or other SAML/OIDC providers.
129+
# The use of Keycloak as bridge between OpenCloud and other identity providers creates more control over the
130+
# authentication process, the allowed clients and the session management.
131+
# Keycloak also manages the Role Based Access Control (RBAC) for OpenCloud.
132+
# Keycloak can be used in two different modes:
133+
# 1. Autoprovisioning: New users are automatically created in openCloud when they log in for the first time.
134+
# 2. Shared User Directory: Users are created in Keycloak and can be used in OpenCloud immediately
135+
# because the LDAP server is connected to both Keycloak and OpenCloud.
136+
# Only use one of the two modes at a time.
137+
138+
## Autoprovisioning Mode ##
139+
# Use together with idm/external-idp.yml
140+
# If you want to use a keycloak for local testing, you can use testing/external-keycloak.yml and testing/ldap-manager.yml
141+
# Domain of your Identity Provider.
142+
IDP_DOMAIN=
143+
# IdP Issuer URL, which is used to identify the Identity Provider.
144+
# We need the complete URL, including the protocol (http or https) and the realm.
145+
# Example: "https://keycloak.opencloud.test/realms/openCloud"
146+
IDP_ISSUER_URL=
147+
# Url of the account edit page from your Identity Provider.
148+
IDP_ACCOUNT_URL=
149+
150+
## Shared User Directory Mode ##
151+
# Use together with idm/ldap-keycloak.yml and traefik/ldap-keycloak.yml
152+
# Domain for Keycloak. Defaults to "keycloak.opencloud.test".
153+
KEYCLOAK_DOMAIN=
154+
# Admin user login name. Defaults to "kcadmin".
155+
KEYCLOAK_ADMIN=
156+
# Admin user login password. Defaults to "admin".
157+
KEYCLOAK_ADMIN_PASSWORD=
158+
# Keycloak Database username. Defaults to "keycloak".
159+
KC_DB_USERNAME=
160+
# Keycloak Database password. Defaults to "keycloak".
161+
KC_DB_PASSWORD=
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Development/Test Deployment for a multi-tenacy setup
2+
3+
The docker compose files in this directory are derived from the
4+
opencloud-compose project and can be used to deploy a Development or Testing
5+
environment for a multi-tenancy setup of OpenCloud. It consists of the
6+
following services:
7+
8+
* `provisioning`: The OpenCloud graph service deployed in a standalone mode. It
9+
is configured to provide the libregraph education API for managing tenants
10+
and users. The `ldap-server`service (see below) is used to store the tenants
11+
and users.
12+
* `ldap-server`: An OpenLDAP server that is used by the provisioning service to
13+
store tenants and users. Used by the OpenCloud services as the user directory
14+
(for looking up users and searching for sharees).
15+
* `keycloak`: The OpenID Connect Provider used for authenticating users. The
16+
pre-loaded realm is configured to add `tenantid` claim into the identity and
17+
access tokens. It's also currently consuming user from the `ldap-server`
18+
(this federation will likely go away in the future and is optional for future
19+
configurations).
20+
* `opencloud`: The OpenCloud configured so that is hides users from different
21+
tenants from each other.
22+
23+
To deploy the setup, run:
24+
25+
```bash
26+
docker compose -f docker-compose.yml -f keycloak.yml -f ldap-server.yml -f traefik.yml up
27+
```
28+
29+
Once deployed you can use the `initialize_users.go` to create a couple of example
30+
tenants and some users in each tenant:
31+
32+
* Tenant `Famous Coders` with users `dennis` and `grace`
33+
* Tenant `Scientists` with users `einstein` and `marie`
34+
35+
The passwords for the users is set to `demo` in keycloak
36+
37+
```
38+
> go run initialize_users.go
39+
Created tenant: Famous Coders with id fc58e19a-3a2a-4afc-90ec-8f94986db340
40+
Created user: Dennis Ritchie with id ee1e14e7-b00b-4eec-8b03-a6bf0e29c77c
41+
Created user: Grace Hopper with id a29f3afd-e4a3-4552-91e8-cc99e26bffce
42+
Created tenant: Scientists with id 18406c53-e2d6-4e83-98b6-a55880eef195
43+
Created user: Albert Einstein with id 12023d37-d6ce-4f19-a318-b70866f265ba
44+
Created user: Marie Curie with id 30c3c825-c37d-4e85-8195-0142e4884872
45+
Setting password for user: grace
46+
Setting password for user: marie
47+
Setting password for user: dennis
48+
Setting password for user: einstein
49+
```

devtools/deployments/multi-tenancy/certs/.gitkeep

Whitespace-only changes.

devtools/deployments/multi-tenancy/certs/acme.json

Whitespace-only changes.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"clientId": "OpenCloudAndroid",
3+
"name": "OpenCloud Android App",
4+
"surrogateAuthRequired": false,
5+
"enabled": true,
6+
"alwaysDisplayInConsole": false,
7+
"clientAuthenticatorType": "client-secret",
8+
"redirectUris": [
9+
"oc://android.opencloud.eu"
10+
],
11+
"webOrigins": [],
12+
"notBefore": 0,
13+
"bearerOnly": false,
14+
"consentRequired": false,
15+
"standardFlowEnabled": true,
16+
"implicitFlowEnabled": false,
17+
"directAccessGrantsEnabled": true,
18+
"serviceAccountsEnabled": false,
19+
"publicClient": true,
20+
"frontchannelLogout": false,
21+
"protocol": "openid-connect",
22+
"attributes": {
23+
"saml.assertion.signature": "false",
24+
"saml.force.post.binding": "false",
25+
"saml.multivalued.roles": "false",
26+
"saml.encrypt": "false",
27+
"post.logout.redirect.uris": "oc://android.opencloud.eu",
28+
"backchannel.logout.revoke.offline.tokens": "false",
29+
"saml.server.signature": "false",
30+
"saml.server.signature.keyinfo.ext": "false",
31+
"exclude.session.state.from.auth.response": "false",
32+
"backchannel.logout.session.required": "true",
33+
"client_credentials.use_refresh_token": "false",
34+
"saml_force_name_id_format": "false",
35+
"saml.client.signature": "false",
36+
"tls.client.certificate.bound.access.tokens": "false",
37+
"saml.authnstatement": "false",
38+
"display.on.consent.screen": "false",
39+
"saml.onetimeuse.condition": "false"
40+
},
41+
"authenticationFlowBindingOverrides": {},
42+
"fullScopeAllowed": true,
43+
"nodeReRegistrationTimeout": -1,
44+
"defaultClientScopes": [
45+
"web-origins",
46+
"profile",
47+
"roles",
48+
"groups",
49+
"basic",
50+
"email"
51+
],
52+
"optionalClientScopes": [
53+
"address",
54+
"phone",
55+
"offline_access",
56+
"microprofile-jwt"
57+
],
58+
"access": {
59+
"view": true,
60+
"configure": true,
61+
"manage": true
62+
}
63+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"clientId": "OpenCloudDesktop",
3+
"name": "OpenCloud Desktop Client",
4+
"surrogateAuthRequired": false,
5+
"enabled": true,
6+
"alwaysDisplayInConsole": false,
7+
"clientAuthenticatorType": "client-secret",
8+
"redirectUris": [
9+
"http://127.0.0.1",
10+
"http://localhost"
11+
],
12+
"webOrigins": [],
13+
"notBefore": 0,
14+
"bearerOnly": false,
15+
"consentRequired": false,
16+
"standardFlowEnabled": true,
17+
"implicitFlowEnabled": false,
18+
"directAccessGrantsEnabled": true,
19+
"serviceAccountsEnabled": false,
20+
"publicClient": true,
21+
"frontchannelLogout": false,
22+
"protocol": "openid-connect",
23+
"attributes": {
24+
"saml.assertion.signature": "false",
25+
"saml.force.post.binding": "false",
26+
"saml.multivalued.roles": "false",
27+
"saml.encrypt": "false",
28+
"post.logout.redirect.uris": "+",
29+
"backchannel.logout.revoke.offline.tokens": "false",
30+
"saml.server.signature": "false",
31+
"saml.server.signature.keyinfo.ext": "false",
32+
"exclude.session.state.from.auth.response": "false",
33+
"backchannel.logout.session.required": "true",
34+
"client_credentials.use_refresh_token": "false",
35+
"saml_force_name_id_format": "false",
36+
"saml.client.signature": "false",
37+
"tls.client.certificate.bound.access.tokens": "false",
38+
"saml.authnstatement": "false",
39+
"display.on.consent.screen": "false",
40+
"saml.onetimeuse.condition": "false"
41+
},
42+
"authenticationFlowBindingOverrides": {},
43+
"fullScopeAllowed": true,
44+
"nodeReRegistrationTimeout": -1,
45+
"defaultClientScopes": [
46+
"web-origins",
47+
"profile",
48+
"roles",
49+
"groups",
50+
"basic",
51+
"email"
52+
],
53+
"optionalClientScopes": [
54+
"address",
55+
"phone",
56+
"offline_access",
57+
"microprofile-jwt"
58+
],
59+
"access": {
60+
"view": true,
61+
"configure": true,
62+
"manage": true
63+
}
64+
}

0 commit comments

Comments
 (0)