From 432e61f54adee2c4165bbfedf0eaf39892ceb5e8 Mon Sep 17 00:00:00 2001 From: darta Date: Thu, 8 Apr 2021 11:52:16 +0000 Subject: [PATCH] Added etherpad --- .gitignore | 3 +- .gitmodules | 6 + Makefile | 92 ++++++++++++++++ README.md | 18 +++ config/Makefile | 13 +++ config/dd.sh | 16 +++ config/keycloak/realm.json | 116 ++++++++++++++++++++ digitaldemocratic.conf.example | 78 +++++++++++++ docs/SAML_README.md | 194 +++++++++++++++++++++++++++++++++ docs/develop.md | 50 +++++++++ isard-apps | 1 + isard-sso | 1 + 12 files changed, 587 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 Makefile create mode 100644 config/Makefile create mode 100644 config/dd.sh create mode 100644 config/keycloak/realm.json create mode 100644 digitaldemocratic.conf.example create mode 100644 docs/SAML_README.md create mode 100644 docs/develop.md create mode 160000 isard-apps create mode 160000 isard-sso diff --git a/.gitignore b/.gitignore index a48cf0d..c47613f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -public +digitaldemocratic.conf +*.yml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9a9004f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "isard-apps"] + path = isard-apps + url = https://gitlab.com/isard/isard-apps +[submodule "isard-sso"] + path = isard-sso + url = https://gitlab.com/isard/isard-sso diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..17a4196 --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +#!make +include digitaldemocratic.conf +export $(shell sed 's/=.*//' digitaldemocratic.conf) + +VERSION := 0.0.1-rc0 +export VERSION + +BUILD_ROOT_PATH=$(shell pwd) + +environment: + cp digitaldemocratic.conf isard-apps/.env + echo "BUILD_ROOT_PATH=$(BUILD_ROOT_PATH)/isard-apps" >> isard-apps/.env + cp isard-apps/.env isard-apps/docker/postgresql && \ + cp isard-apps/.env isard-apps/docker/mariadb && \ + cp isard-apps/.env isard-apps/docker/moodle && \ + cp isard-apps/.env isard-apps/docker/nextcloud && \ + cp isard-apps/.env isard-apps/docker/wordpress && \ + cp isard-apps/.env isard-apps/docker/etherpad + + cp digitaldemocratic.conf isard-sso/docker-compose-parts/.env + echo "BUILD_ROOT_PATH=$(BUILD_ROOT_PATH)/isard-sso" >> isard-sso/docker-compose-parts/.env + +build: environment + docker-compose -f isard-sso/docker-compose-parts/haproxy.yml \ + -f isard-sso/docker-compose-parts/freeipa.yml \ + -f isard-sso/docker-compose-parts/keycloak.yml \ + -f isard-sso/docker-compose-parts/avatars.yml \ + -f isard-apps/docker/postgresql/postgresql.yml \ + config > sso.yml + docker-compose -f isard-apps/docker/moodle/moodle.yml \ + -f isard-apps/docker/nextcloud/nextcloud.yml \ + -f isard-apps/docker/wordpress/wordpress.yml \ + -f isard-apps/docker/etherpad/etherpad.yml \ + -f isard-apps/docker/onlyoffice/onlyoffice.yml \ + -f isard-apps/docker/redis/redis.yml \ + -f isard-apps/docker/postgresql/postgresql.yml \ + -f isard-apps/docker/mariadb/mariadb.yml \ + -f isard-apps/docker/network.yml \ + config > apps.yml + docker-compose -f sso.yml -f apps.yml config > docker-compose.yml + rm sso.yml apps.yml + docker-compose build + +up: build + docker-compose up -d --no-deps + +down: + docker-compose down + +remove: down + rm -rf /opt/digitaldemocratic/postgres + rm -rf /opt/digitaldemocratic/redis + rm -rf /opt/digitaldemocratic/wordpress + rm -rf /opt/digitaldemocratic/nextcloud + rm -rf /opt/digitaldemocratic/mariadb + rm -rf /opt/digitaldemocratic/freeipa + # Leaves haproxy folder with certificates. Remove manually to get new certificates. + +add-plugins: + # Nextcloud + #cp -R $$BUILD_ROOT_PATH/isard-apps/docker/nextcloud/themes/* $$DATA_FOLDER/nextcloud/themes/ + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings app:disable firstrunwizard + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings app:install forms + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings app:install polls + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings app:install calendar + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:system:set theme --value=digitaldemocratic + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:system:set allow_local_remote_servers --value=true + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings maintenance:theme:update + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:disable dashboard'" + + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:install mail'" + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:enable mail'" + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:install user_saml'" + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:enable user_saml'" + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:install ownpad'" + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "/ownpad_cfg.sh" + docker exec -ti isard-apps-nextcloud-app /bin/sh -c "su - www-data -s /bin/sh -c 'PHP_MEMORY_LIMIT=512M php /var/www/html/occ app:enable ownpad'" + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:app:set ownpad ownpad_etherpad_enable --value="yes" + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:app:set ownpad ownpad_etherpad_host --value="https://pad.$$DOMAIN" + + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings app:install onlyoffice + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:app:set onlyoffice DocumentServerUrl --value="https://oof.$$DOMAIN" + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:app:set onlyoffice jwt_secret --value="secret" + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:app:set onlyoffice jwt_header --value="Authorization" + docker exec -u www-data isard-apps-nextcloud-app php occ --no-warnings config:system:set allow_local_remote_servers --value=true + + # Wordpress + ## Multisite + docker exec -ti isard-apps-wordpress /bin/sh -c "/multisite.sh" + +connect-saml: + while [ "`docker inspect -f {{.State.Health.Status}} isard-apps-moodle`" != "healthy" ]; do sleep 2; done \ No newline at end of file diff --git a/README.md b/README.md index f64e552..a30ddb8 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,21 @@ This documentation is writed in Markdown using [MkDocs+Gitlab](https://gitlab.com/pages/mkdocs). See `docs` directory for Markdown files or the [auto-built site](https://digitaldemocratic.gitlab.io/digitaldemocratic). + +## Quick start + +``` +cp digitaldemocratic.conf.example digitaldemocratic.conf +``` + +Edit digitaldemocratic.conf file variables to suit your needs. + +``` +make up +``` + +Wait till apps come up and add plugins: + +``` +make add-plugins +``` diff --git a/config/Makefile b/config/Makefile new file mode 100644 index 0000000..8337cb8 --- /dev/null +++ b/config/Makefile @@ -0,0 +1,13 @@ +#!make +include ../digitaldemocratic.conf +export $(shell sed 's/=.*//' ../digitaldemocratic.conf) + +VERSION := 0.0.1-rc0 +export VERSION + +dump-keycloak-realm: + docker exec -i isard-sso-keycloak sh -c '/opt/jboss/keycloak/bin/kcadm.sh \ + config credentials --server http://localhost:8080/auth \ + --realm master --user $(KEYCLOAK_ADMIN_USER) --password $(KEYCLOAK_ADMIN_PASSWORD) &> /dev/null && \ + /opt/jboss/keycloak/bin/kcadm.sh \ + get realms/DigitalDemocratic' > keycloak/realm.json diff --git a/config/dd.sh b/config/dd.sh new file mode 100644 index 0000000..4befaa5 --- /dev/null +++ b/config/dd.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../digitaldemocratic.conf + +echo "Dump realm.json" +docker exec -i isard-sso-keycloak sh -c '/opt/jboss/keycloak/bin/kcadm.sh \ + config credentials --server http://localhost:8080/auth \ + --realm master --user $KEYCLOAK_USER --password $KEYCLOAK_PASSWORD &> /dev/null && \ + /opt/jboss/keycloak/bin/kcadm.sh \ + get realms/DigitalDemocratic' > keycloak/realm.json + +echo "Dump realm.json" +docker exec -i isard-sso-keycloak sh -c '/opt/jboss/keycloak/bin/kcadm.sh \ + config credentials --server http://localhost:8080/auth \ + --realm master --user $KEYCLOAK_USER --password $KEYCLOAK_PASSWORD &> /dev/null && \ + /opt/jboss/keycloak/bin/kcadm.sh \ + get realms/DigitalDemocratic' > keycloak/realm.json \ No newline at end of file diff --git a/config/keycloak/realm.json b/config/keycloak/realm.json new file mode 100644 index 0000000..4285afc --- /dev/null +++ b/config/keycloak/realm.json @@ -0,0 +1,116 @@ +{ + "id" : "DigitalDemocratic", + "realm" : "DigitalDemocratic", + "displayName" : "Digital Democratic", + "displayNameHtml" : "
Digital Democratic
", + "notBefore" : 0, + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : true, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : true, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "defaultRoles" : [ "offline_access", "uma_authorization" ], + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { + "password" : "**********", + "starttls" : "true", + "auth" : "true", + "port" : "587", + "host" : "mail.gandi.net", + "from" : "info@digitaldemocratic.net", + "fromDisplayName" : "Digital Democratic", + "ssl" : "true", + "user" : "info@digitaldemocratic.net" + }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "clientOfflineSessionMaxLifespan" : "0", + "clientSessionIdleTimeout" : "0", + "clientSessionMaxLifespan" : "0", + "clientOfflineSessionIdleTimeout" : "0" + }, + "userManagedAccessAllowed" : true +} \ No newline at end of file diff --git a/digitaldemocratic.conf.example b/digitaldemocratic.conf.example new file mode 100644 index 0000000..f8fd708 --- /dev/null +++ b/digitaldemocratic.conf.example @@ -0,0 +1,78 @@ +## GLOBALS + +DOMAIN=mydomain.com +LETSENCRYPT_DNS= +LETSENCRYPT_EMAIL= +GANDI_KEY= + +DB_FOLDER=/opt/digitaldemocratic/db +DATA_FOLDER=/opt/digitaldemocratic/data +SRC_FOLDER=/opt/digitaldemocratic/src + +LANG=es_ES.UTF-8 +LANGUAGE=es_ES:ca + +SMTP_HOST=smtp.mymailserver.com +SMTP_PORT=587 +SMTP_USER=your_email@mymailserver.com +SMTP_PASSWORD=SuperSecret +SMTP_PROTOCOL=tls + +### FREEIPA (ipa) +########################################################################### +IPA_ADMIN_PWD=freeipafreeipa + +### KEYCLOAK (sso) +########################################################################### +KEYCLOAK_USER=admin +KEYCLOAK_PASSWORD=keycloakkeycloak + +KEYCLOAK_DB_ADDR=isard-apps-postgresql +KEYCLOAK_DB_DATABASE=keycloak +KEYCLOAK_DB_USER=keycloak +KEYCLOAK_DB_PASSWORD=keycloakkeycloak + +### POSTGRES +########################################################################### +POSTGRES_PASSWORD=postgrespostgres +POSTGRES_USER=admin + +## MARIADB ADMIN +###MARIADB_USER=root +MARIADB_PASSWORD=SuperSecret + +## MOODLE +MOODLE_POSTGRES_USER=moodle +MOODLE_POSTGRES_PASSWORD=M00dl3 + +MOODLE_ADMIN_USER=admin +MOODLE_ADMIN_PASSWORD=M00dl3 + +MOODLE_SITENAME="Digital Democratic" + +MOODLE_EMAIL=moodle-info@mymailserver.com +MOODLE_MAIL_NOREPLY_ADDRESS=noreply@mymailserver.com +MOODLE_MAIL_PREFIX=[moodle] + +## NEXTCLOUD +NEXTCLOUD_POSTGRES_USER=nextcloud +NEXTCLOUD_POSTGRES_PASSWORD=N3xtcl0ud + +NEXTCLOUD_ADMIN_USER=admin +NEXTCLOUD_ADMIN_PASSWORD=N3xtcl0ud + +## ETHERPAD +ETHERPAD_POSTGRES_USER=etherpad +ETHERPAD_POSTGRES_PASSWORD=3th3rpad + +ETHERPAD_ADMIN_USER=admin +ETHERPAD_ADMIN_PASSWORD=SuperSecret +#ETHERPAD_API_KEY=NotImplemented + +## WORDPRESS +WORDPRESS_MARIADB_USER=wordpress +WORDPRESS_MARIADB_PASSWORD=W0rdpr3ss + +WORDPRESS_ADMIN_USER=admin +WORDPRESS_ADMIN_PASSWORD=W0rdpr3ss + diff --git a/docs/SAML_README.md b/docs/SAML_README.md new file mode 100644 index 0000000..2755c1d --- /dev/null +++ b/docs/SAML_README.md @@ -0,0 +1,194 @@ +# SAML Authentication + +The authentication it is done with SAML plugins in the apps agains a central Keycloak identity provider (IdP) server. As the integration of client SAML with IdP is quite tedious this document describes how to integrate some of this apps into your keycloak server. + +## Keycloak + +The identity provider administration interface can be reached at https://sso.. There you can add client apps, roles, groups, users, mappers, etc... Please read documentation at: https://www.keycloak.org/documentation + +## Applications + +In this document we will cover **Moodle**, **Nextcloud** and **Wordpress** SAML configuration plugins. + +### Moodle + +Install SAML plugin and follow this steps in **Moodle**: + +1. Activate SAML2 plugin at the **Extensions** -> **Authentication** in Moodle. You should click on the eye. Then enter de *configuration* link. +2. Click on the **Regenerate SP certificate** button. Optionally set up your desired certificate data and accept. You will need to get back to SAML2 configuration plugin afterwards. The direct link page is: https://moodle./auth/saml2/regenerate.php +3. Click on the **Lock down** certificate button and accept. This will avoid SAML2 plugin to regenerate the certificate each time we restart Moodle (why has this annoying behaviour?) +4. Download **SAML2 Service Provider** xml and save it in a file (better right click and save to file). The direct link page is: https://moodle./auth/saml2/sp/metadata.php + +Now go to your *keycloak* admin (https://sso..) and: + +1. At **Clients** menú go to **create** new client and import the moodle **SAML2 Service Provider** xml and accept. The direct link is: https://sso./auth/admin/master/console/#/create/client/master +2. Now go to **Mappers** tab in this client and add this builtins: + 1. *email* + 2. *givenName* + 3. *surname* +3. Now create **Custom Mapper** for username: + 1. Name: `username` + Mapper Type: *User Property* + Property: `username` + Friendly Name: `username` + SAML Attribute Name: `username` + SAML Attribute NameFormat: *Basic* +4. Now *copy* the keycloak **SAML IdP xml data +5. Copy keycloak **SAML 2.0 Identity Provider Metadata** xml from **Realm Settings** and paste it into moodle SAML2 plugin **IdP metadata xml OR public xml URL** textbox. Note that you should copy it from a text editor, not the content from the browser view! The content should be one-liner!!! No break lines even it is an xml file. + +Now go back to Moodle (if not already there as you just copied the IdP metadata into de SAML2 plugin) and set up this options in the SAML2 plugin: + +- **Dual login**: No. But you should be aware that setting to *No* will automatically redirect from now on the logins to Keycloak SSO login page and you won't be able to access your moodle instance as admin if you don't use the alternate url **/login/index.php?saml=off**. This is what you want when you have checked that the SAML2 plugin is working as expected. +- **Mapping idP**: username +- **Auto create users**: Yes +- **Role Mapping**: Configure the same roles you created in keycloak for users. For example: + - Site administrators: admin + - Course creator: coursecreator + - Manager: manager +- **Data mapping**: With at least this fields moodle will skip user profile fill the first time he logs in as this three are the only required. You can set up more mappers in keycloak for this moodle SP and map it to the rest of the fields. + +If everything went ok you should now be redirected to Keycloak SSO login page and you can log in into your moodle with the users you already created in Keycloak and with the role assigned to them. + +### NEXTCLOUD + +TODO: Does not map email nor friendlyname (display name). Also not tested to add quota field in keycloak and map it to nextcloud. + +(all credits to this hell set up goes to: https://janikvonrotz.ch/2020/04/21/configure-saml-authentication-for-nextcloud-with-keycloack/, RESPECT) + +BEAWARE: of the good programmers, but very bad designers (I empathyze with them but...) The SAML plugin in nextcloud has some greyed out texts that are links! Damn, who did that! You don't realize that are links that open a lot of options that need to be filled in! + +1. Copy the Keycloak realm RSA certificate from **Realm Settings** menu, in the **Keys** tab by clicking in the **Certificate** button of **RSA** (not the public key). It will show it in a modal form, just select it, copy and save it into file for later use. +2. Generate Nextcloud SP keys. Sorry, this step is needed. So you should generate your own ones. If you don't know how to install this just enter the nextcloud container (docker exec -ti isard-apps-nextcloud-app /bin/sh) and run the command there and copy the contents elsewhere with the *private.key* and *public.cert* names. + 1. **openssl req -nodes -new -x509 -keyout private.key -out public.cert** +3. Install SAML plugin. Select **Integrated configuration** at first config page. +4. Configure at: https://nextcloud./settings/admin/saml or going to the **Settings** options in user menú. + 1. **General** + 1. Input box: **Attribute to map the UID to**: username + 2. Input box: **Optional display name**: *anything you want as this won't be shown when we activate the direct redirect to keycloak SSO login. + 2. **Service Provider Data**: WARNING: Copy them with BEGIN/END tags! WARNING nº2: You should click on the greyed out link, that doesn't seem a link, to the end of the line. + 1. **x509**: public.key (generated before) + 2. **Private key**: private.key (generated before) + 3. **Identity Provider Data** + 1. **Identifier of the IdP**: https://sso./auth/realms/master + 2. **URL target of the IdP**: https://sso./auth/realms/master/protocol/saml + 3. **URL Location of the IdP SLO request**: https://sso./auth/realms/poc/protocol/saml + 4. **Public X.509 certificate**: (The *RSA Certificate* from keycloak at the very first step number 1). + 4. **Attribute mapping** + 1. **email**: email + 2. **user groups**: Role + 5. **Security Settings** (check only this options) + 1. **Signatures and encryption offered** + 1. + 2. + 3. + 2. **Signatures and encryption required** + 1. + 2. [Metadata of the SP will offer this info] + 6. Click and save the xml metadata from the bottom page button **Download XML metadata**. + +If you reached this point you are almost done with Nextcloud SAML configuration if the *annoying* live update of this plugin page shows at the bottom the **Download XML metadata** with no errors. Now let's go back to **Keycloak admin console** and finish configuration. + +1. At **Clients** menú go to **create** new client and import the nextcloud **SAML2 Service Provider** xml that you just downloaded and accept. The direct link is: https://sso./auth/admin/master/console/#/create/client/master. + 1. My guru that I referenced at the beginning of this documentation says that you should set the **Client SAML Endpoint** to https://sso./auth/realms/master prior to accepting the uploaded xml data. I tested that this is not really needed. +2. Now go to **Mappers** tab in this client and create **Custom Mapper** fields: NOTE: ONLY USERNAME and ROLES WORKING. Nextcloud doesn't get email + 1. Name: `username` + Mapper Type: *User Property* + Property: `username` + Friendly Name: `username` + SAML Attribute Name: `username` + SAML Attribute NameFormat: *Basic* + 2. Add builtins:Name: `email` + Mapper Type: *User Property* + Property: `email` + Friendly Name: `email` + SAML Attribute Name: `email` + SAML Attribute NameFormat: *Basic* + 3. Name: `roles` + Mapper Type: *Role List* + Role attribute name: `Roles` + Friendly Name: `Roles` + SAML Attribute NameFormat: *Basic* + Single Role Attribute: *On* +3. Then the main role seem to be from a single role attribute that should be set up in... + 1. **Client scopes** menu + 1. role_list + 1. Mappers tab + 1. role list + 1. Single Role Attribute, that should be checked. + +Now you should be able to test your Keycloak users/roles against nextcloud. If you need to access as admin into nextcloud again you should use this end url for your nextcloud domain: **/login?direct=1** + +#### Debug SAML plugin + +Trust me, this is important to be here as many settings/options/checkboxes can be missconfigured if you were not really awaken today. + +Edit in the outside mount volume (/opt/digitaldemocratic/db/src/nextcloud/config/config.php) and restart nextcloud container (docker restart isard-apps-nextcloud-app): + + true, + +..... + +### WORDPRESS +If you already set up Moodle and Nextcloud SAML plugins you are already the master of the universe and I will go faster at describing this one as you want to finish this. + +NOTE: Client Id in Keycloak has to be exactly **php-saml**. It could be modified and set up at wordpress saml plugin (but better don't do experiments) + +1. Install **OneLogin SAML plugin** +2. **STATUS** + 1. Enable +3. **IDENTITY PROVIDER SETTINGS** + 1. IdP ENTITY ID: Anything you want as won't be shown because we will redirect all logins to Keycloak SSO. + 1. **SSO Service Url**: https://sso.digitaldemocratic.net/auth/realms/master/protocol/saml + 2. **SLO Service Url**: https://sso.digitaldemocratic.net/auth/realms/master/protocol/saml + 3. **X.509 Certificate**: Copy the Certificate (not the Public key) from the keycloak realm (https://sso.digitaldemocratic.net/auth/admin/master/console/#/realms/master/keys) without the begin/end lines in the cert. +4. **OPTIONS** + 1. Create user if not exists + 2. Update user data + 3. Force SAML login (To access as admin look for the url at the end of this part) + 4. Single Log Out + 5. Match Wordpress account by: username ??? +5. **ATTRIBUTE MAPPING** + 1. Username: username + 2. Email: email + 4. First Name: givenName + 5. Last Name: sn + 6. Role: Role +6. **ROLE MAPPING** + 1. Administrator: admins + 2. Editor: managers + 3. Author: coursecreators + ... + 4. Multiple role values...: true +7. **CUSTOMIZE ACTIONS AND LINKS** + 1. Stay in WordPress after SLO +8. **ADVANCED SETTINGS** + 1. Sign AuthnRequest + 2. Sign LogoutRequest + 3. Sign LogoutResponse + 4. Service Provider X.509 Certificate & Service Provider Private Key: Generate both and paste it without the begin/end lines: + openssl req -nodes -new -x509 -keyout private.key -out public.cert + +9. Download **Service Provider metadata** from top and add it to keycloak clients menu +10. Keycloak client mappers: + 1. Name: `username` + Mapper Type: *User Property* + Property: `username` + Friendly Name: `username` + SAML Attribute Name: `username` + SAML Attribute NameFormat: *Basic* + 2. Add builtins:Name: `email` + Mapper Type: *User Property* + Property: `email` + Friendly Name: `email` + SAML Attribute Name: `email` + SAML Attribute NameFormat: *Basic* + 3. Name: `roles` + Mapper Type: *Role List* + Role attribute name: `Roles` + Friendly Name: `Roles` + SAML Attribute NameFormat: *Basic* + Single Role Attribute: *On* + +To access as an admin again you should use the url: https://wp./wp-login.php?normal \ No newline at end of file diff --git a/docs/develop.md b/docs/develop.md new file mode 100644 index 0000000..079aca6 --- /dev/null +++ b/docs/develop.md @@ -0,0 +1,50 @@ +## SAML2 Plugin development environment (moodle) + +NOTE: This could be completely outdated as the current version mounts moodle html source outside the container. + +All this have to be done as the image doesn't let html external folder mounted as volume (image doesn't use root) + +1. Start isard-apps-moodle docker with default config. Wait for moodle to be ready. +2. Enter docker and copy html to external folder: + 1. docker exec -ti isard-apps-moodle /bin/sh + 2. cd /var/www/html + 3. mkdir /var/www/moodledata/html + 4. cp -R . /var/www/moodledata/html + +Now you open two terminals: + +- docker exec -ti isard-apps-moodle /bin/sh +- docker logs isard-apps-moodle --follow + +You can edit saml2 plugin from host (/opt/isard-office/moodle/data/html/auth/saml2) and copy it to the current html folder: + +- /var/www/html/auth/saml2 $ cp -R /var/www/moodledata/html/auth/saml2/* . + +When you finish developing get the new plugin code into a zip and in the correct src folder: + +- cd ${DATA_FOLDER}/moodle/data/html/auth/ && zip -r /isard-office/docker/moodle/plugins/auth_saml2.zip saml2 + +## SAML2 Plugin src + +The modified source files are: + +- auth.php (lines 570 to 595, sync_roles call added) +- locallib.php (function sync_roles) + +Also the common plugin setup fields and lang strings: + +- settings.php (lines 314 to 333) +- lang/en/auth_saml2.php (lines 24 to 29) + +# Big Blue Button + +TODO: + +- Audio fails with docker in iptables=false and managed by firewalld in masquerade mode. This is due to coturn that doesn't like being behind nat. +- Firewalld + BBB: As BBB will 'take' the host interface we should: + - Remove /etc/docker/daemon.json the iptables: false + - firewall-cmd --zone=public --remove-interface=docker0 --permanent + - firewall-cmd --zone=docker --add-interface=docker0 --permanent + - Now the docker applies iptables as per container. Note that we don't have control over this from now on. +- Scalelite +- Script creation of base debian with virt-install and then replicate BBBs (partially done) \ No newline at end of file diff --git a/isard-apps b/isard-apps new file mode 160000 index 0000000..6b3f271 --- /dev/null +++ b/isard-apps @@ -0,0 +1 @@ +Subproject commit 6b3f2711cb93f4e06f287f2e25cffefa62247901 diff --git a/isard-sso b/isard-sso new file mode 160000 index 0000000..fa66b7c --- /dev/null +++ b/isard-sso @@ -0,0 +1 @@ +Subproject commit fa66b7c37db18b24b293ec9cee2c2cbca9ac9691