From 36feb5062d301811a9820b149cac9de2d6fdfb67 Mon Sep 17 00:00:00 2001 From: 3wc <3wc.git@doesthisthing.work> Date: Sat, 5 Sep 2020 14:18:00 +0200 Subject: [PATCH 1/5] First stab at SimpleSAMLPHP Main issue is how to customise the virtual host configuration of the Mediawiki container to pass /simplesamlphp/ through to the right directory (or reverse proxy to the `simplesamlphp` container) --- compose.yml | 28 ++++++++++ metadata/saml20-idp-hosted.php | 93 ++++++++++++++++++++++++++++++++ metadata/saml20-idp-remote.php | 60 +++++++++++++++++++++ metadata/saml20-sp-remote.php | 96 ++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 metadata/saml20-idp-hosted.php create mode 100644 metadata/saml20-idp-remote.php create mode 100644 metadata/saml20-sp-remote.php diff --git a/compose.yml b/compose.yml index 3374392..c8aaa2d 100644 --- a/compose.yml +++ b/compose.yml @@ -34,6 +34,7 @@ services: volumes: - 'mediawiki_images:/var/www/html/images' - 'parsoid:/usr/lib/parsoid' + - 'simplesaml:/var/www/html/simplesamlphp' configs: - source: LocalSettings_conf target: /var/www/html/LocalSettings.php @@ -60,11 +61,38 @@ services: - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" entrypoint: /docker-entrypoint2.sh + simplesamlphp: + image: venatorfox/simplesamlphp:latest + environment: + - CONFIG_BASEURLPATH=${DOMAIN}/simplesamlphp + - CONFIG_AUTHADMINPASSWORD={SSHA256}MjJSiMlkQLa+fqI+CmQ1x1oUJ7OGucYpznKxBBHpgfC+Oh+7B9vgGw== + - CONFIG_SECRETSALT=exampleabcdefghijklmnopqrstuvwxy + - CONFIG_TECHNICALCONTACT_NAME=Adam W Zheng + - CONFIG_TECHNICALCONTACT_EMAIL=helo@autonomic.zone + - CONFIG_SHOWERRORS=true + - CONFIG_ERRORREPORTING=true + - CONFIG_ADMINPROTECTINDEXPAGE=true + - CONFIG_LOGGINGLEVEL=INFO + - CONFIG_ENABLESAML20IDP=true + #- CONFIG_STORETYPE=memcache + #- CONFIG_MEMCACHESTOREPREFIX=simplesamlphp + #- CONFIG_MEMCACHESTORESERVERS= 'memcache_store.servers' => [\n [\n ['hostname' => 'some-memcacheda01'],\n ['hostname' => 'some-memcacheda02'],\n ],\n [\n ['hostname' => 'some-memcachedb01'],\n ['hostname' => 'some-memcachedb02'],\n ], + - OPENLDAP_TLS_REQCERT=allow + - MTA_NULLCLIENT=false + - POSTFIX_MYHOSTNAME=${DOMAIN} + - POSTFIX_MYORIGIN=$$mydomain + - POSTFIX_INETINTERFACES=loopback-only + - DOCKER_REDIRECTLOGS=true + volumes: + - simplesaml:/var/simplesamlphp/ + networks: + - internal volumes: mariadb: mediawiki_images: parsoid: + simplesaml: networks: proxy: diff --git a/metadata/saml20-idp-hosted.php b/metadata/saml20-idp-hosted.php new file mode 100644 index 0000000..51da8ec --- /dev/null +++ b/metadata/saml20-idp-hosted.php @@ -0,0 +1,93 @@ + 'wisera.auth.dev.iww.org.uk', + + // X.509 key and certificate. Relative to the cert directory. + 'privatekey' => 'saml.pem', + 'certificate' => 'saml.crt', + + /* + * Authentication source to use. Must be one that is configured in + * 'config/authsources.php'. + */ + 'auth' => 'live', + + /* + * WARNING: SHA-1 is disallowed starting January the 1st, 2014. + * + * Uncomment the following option to start using SHA-256 for your signatures. + * Currently, SimpleSAMLphp defaults to SHA-1, which has been deprecated since + * 2011, and will be disallowed by NIST as of 2014. Please refer to the following + * document for more information: + * + * http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf + * + * If you are uncertain about service providers supporting SHA-256 or other + * algorithms of the SHA-2 family, you can configure it individually in the + * SP-remote metadata set for those that support it. Once you are certain that + * all your configured SPs support SHA-2, you can safely remove the configuration + * options in the SP-remote metadata set and uncomment the following option. + * + * Please refer to the IdP hosted reference for more information. + */ + 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', + + /* Uncomment the following to use the uri NameFormat on attributes. */ + /* + 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', + 'authproc' => array( + // Convert LDAP names to oids. + 100 => array('class' => 'core:AttributeMap', 'name2oid'), + ), + */ + + /* + * Uncomment the following to specify the registration information in the + * exported metadata. Refer to: + * http://docs.oasis-open.org/security/saml/Post2.0/saml-metadata-rpi/v1.0/cs01/saml-metadata-rpi-v1.0-cs01.html + * for more information. + */ + /* + 'RegistrationInfo' => array( + 'authority' => 'urn:mace:example.org', + 'instant' => '2008-01-17T11:28:03Z', + 'policies' => array( + 'en' => 'http://example.org/policy', + 'es' => 'http://example.org/politica', + ), + ), + */ +); + +$metadata['__DYNAMIC:2__'] = array( + 'host' => 'nara.auth.dev.iww.org.uk', + + 'privatekey' => 'saml.pem', + 'certificate' => 'saml.crt', + + 'auth' => 'redcard', + + 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', +); + +$metadata['__DYNAMIC:3__'] = array( + 'host' => 'auth.dev.iww.org.uk', + + 'privatekey' => 'saml.pem', + 'certificate' => 'saml.crt', + + 'auth' => 'default-sp', + + 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', +); diff --git a/metadata/saml20-idp-remote.php b/metadata/saml20-idp-remote.php new file mode 100644 index 0000000..9e65511 --- /dev/null +++ b/metadata/saml20-idp-remote.php @@ -0,0 +1,60 @@ + array( +// 'en' => 'WISE-RA (production)', +// ), +// 'description' => 'Log in using your WISE-RA members area user name.', +// 'SingleSignOnService' => 'https://service.iww.org.uk/simplesaml/saml2/idp/SSOService.php', +// 'SingleLogoutService' => 'https://service.iww.org.uk/simplesaml/saml2/idp/SingleLogoutService.php', +// 'privatekey' => 'saml.pem', +// 'certificate' => 'saml.crt', +// ); +$metadata['https://wisera.auth.dev.iww.org.uk/simplesaml/saml2/idp/metadata.php'] = array( + 'name' => array( + 'en' => 'WISE-RA (dev)', + ), + 'description' => 'Log in using your WISE-RA members area user name.', + 'SingleSignOnService' => 'https://wisera.auth.dev.iww.org.uk/simplesaml/saml2/idp/SSOService.php', + 'SingleLogoutService' => 'https://wisera.auth.dev.iww.org.uk/simplesaml/saml2/idp/SingleLogoutService.php', + 'privatekey' => 'saml.pem', + 'certificate' => 'saml.crt', +); +$metadata['https://nara.auth.dev.iww.org.uk/simplesaml/saml2/idp/metadata.php'] = array( + 'name' => array( + 'en' => 'NARA (dev)', + ), + 'description' => 'Log in using your NARA red card username.', + 'SingleSignOnService' => 'https://nara.auth.dev.iww.org.uk/simplesaml/saml2/idp/SSOService.php', + 'SingleLogoutService' => 'https://nara.auth.dev.iww.org.uk/simplesaml/saml2/idp/SingleLogoutService.php', + 'privatekey' => 'saml.pem', + 'certificate' => 'saml.crt', +); + +/* + * Guest IdP. allows users to sign up and register. Great for testing! + */ +/* +$metadata['https://openidp.feide.no'] = array( + 'name' => array( + 'en' => 'Feide OpenIdP - guest users', + 'no' => 'Feide Gjestebrukere', + ), + 'description' => 'Here you can login with your account on Feide RnD OpenID. If you do not already have an account on this identity provider, you can create a new one by following the create new account link and follow the instructions.', + + 'SingleSignOnService' => 'https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php', + 'SingleLogoutService' => 'https://openidp.feide.no/simplesaml/saml2/idp/SingleLogoutService.php', + 'certFingerprint' => 'c9ed4dfb07caf13fc21e0fec1572047eb8a7a4cb' +); +*/ + diff --git a/metadata/saml20-sp-remote.php b/metadata/saml20-sp-remote.php new file mode 100644 index 0000000..c0bc787 --- /dev/null +++ b/metadata/saml20-sp-remote.php @@ -0,0 +1,96 @@ + 'https://auth.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', + 'SingleLogoutService' => 'https://auth.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', +); + +/* + * MediaWiki + */ +$metadata['https://mediawiki.dev.iww.org.uk/simplesaml/module.php/saml/sp/metadata.php/default-sp'] = array( + 'AssertionConsumerService' => 'https://mediawiki.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', + 'SingleLogoutService' => 'https://mediawiki.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', +); + +/* + * Moodle + */ +$metadata['https://moodle.dev.iww.org.uk/simplesaml/module.php/saml/sp/metadata.php/default-sp'] = array( + 'AssertionConsumerService' => 'https://moodle.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', + 'SingleLogoutService' => 'https://moodle.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', +); + +/* + * WordPress + */ + $metadata['urn:dev.iww.org.uk'] = array( + 'AssertionConsumerService' => 'https://dev.iww.org.uk/wp/wp-login.php', + 'SingleLogoutService' => 'https://dev.iww.org.uk/wp/wp-login.php', +); +$metadata['urn:shop.dev.iww.org.uk'] = array( + 'AssertionConsumerService' => 'https://shop.dev.iww.org.uk/wp/wp-login.php', + 'SingleLogoutService' => 'https://shop.dev.iww.org.uk/wp/wp-login.php', +); + +/* + * Nextcloud + */ +$metadata['https://cloud.dev.iww.org.uk/apps/user_saml/saml/metadata'] = array( + 'AssertionConsumerService' => 'https://cloud.dev.iww.org.uk/apps/user_saml/saml/acs', + 'SingleLogoutService' => 'https://cloud.dev.iww.org.uk/apps/user_saml/saml/sls', +); + +/* + * RocketChat + */ +$metadata['https://chat.dev.iww.org.uk/_saml/metadata/rc'] = array ( + 'entityid' => 'https://chat.dev.iww.org.uk/_saml/metadata/rc', + 'contacts' => array (), + 'metadata-set' => 'saml20-sp-remote', + 'AssertionConsumerService' => array ( + 0 => array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + 'Location' => 'https://chat.dev.iww.org.uk/_saml/validate/rc', + 'index' => 1, + 'isDefault' => true, + ), + ), + 'SingleLogoutService' => array ( + 0 => array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://chat.dev.iww.org.uk/_saml/logout/rc/', + 'ResponseLocation' => 'https://chat.dev.iww.org.uk/_saml/logout/rc/', + ), + ), + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', +); + +/* + * Example SimpleSAMLphp SAML 2.0 SP + */ +/* $metadata['https://saml2sp.example.org'] = array( + 'AssertionConsumerService' => 'https://saml2sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', + 'SingleLogoutService' => 'https://saml2sp.example.org/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', +); */ + +/* + * This example shows an example config that works with Google Apps for education. + * What is important is that you have an attribute in your IdP that maps to the local part of the email address + * at Google Apps. In example, if your google account is foo.com, and you have a user that has an email john@foo.com, then you + * must set the simplesaml.nameidattribute to be the name of an attribute that for this user has the value of 'john'. + */ +/* $metadata['google.com'] = array( + 'AssertionConsumerService' => 'https://www.google.com/a/g.feide.no/acs', + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', + 'simplesaml.nameidattribute' => 'uid', + 'simplesaml.attributes' => FALSE, +); */ From 40007e53b3596eeb2dac5c9a070c1ae8d3f7d413 Mon Sep 17 00:00:00 2001 From: 3wc <3wc.git@doesthisthing.work> Date: Sun, 13 Sep 2020 14:57:12 +0200 Subject: [PATCH 2/5] Working SimpleSAML --- .envrc.sample | 6 ++++++ compose.yml | 36 +++++++++++++++++++++++++++++------ entrypoint.simplesaml.sh.tmpl | 26 +++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 entrypoint.simplesaml.sh.tmpl diff --git a/.envrc.sample b/.envrc.sample index 0f35ba8..a9fe2d6 100644 --- a/.envrc.sample +++ b/.envrc.sample @@ -8,9 +8,15 @@ export MEDIAWIKI_SITENAMESPACE="Example_Wiki" export MEDIAWIKI_EMAIL_CONTACT="info@wiki.example.com" export MEDIAWIKI_EMAIL_FROM="wiki@wiki.example.com" +export SAML_CONTACT_NAME="Sam Ell" +export SAML_CONTACT_EMAIL="saml@example.com" + export DB_ROOT_PASSWORD_VERSION=v1 export DB_PASSWORD_VERSION=v1 export MEDIAWIKI_SECRET_KEY_VERSION=v1 +export SAML_ADMIN_PASSWORD_VERSION=v1 + export LOCAL_SETTINGS_CONF_VERSION=v1 export HTACCESS_CONF_VERSION=v1 export ENTRYPOINT_CONF_VERSION=v1 +export SAML_ENTRYPOINT_CONF_VERSION=v1 diff --git a/compose.yml b/compose.yml index c8aaa2d..1bd8c73 100644 --- a/compose.yml +++ b/compose.yml @@ -61,14 +61,17 @@ services: - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" entrypoint: /docker-entrypoint2.sh - simplesamlphp: + + simplesaml: image: venatorfox/simplesamlphp:latest + secrets: + - saml_admin_password environment: - - CONFIG_BASEURLPATH=${DOMAIN}/simplesamlphp - - CONFIG_AUTHADMINPASSWORD={SSHA256}MjJSiMlkQLa+fqI+CmQ1x1oUJ7OGucYpznKxBBHpgfC+Oh+7B9vgGw== + - CONFIG_BASEURLPATH=https://${DOMAIN}/simplesaml/ + - CONFIG_AUTHADMINPASSWORD_FILE=/run/secrets/saml_admin_password - CONFIG_SECRETSALT=exampleabcdefghijklmnopqrstuvwxy - - CONFIG_TECHNICALCONTACT_NAME=Adam W Zheng - - CONFIG_TECHNICALCONTACT_EMAIL=helo@autonomic.zone + - CONFIG_TECHNICALCONTACT_NAME=${SAML_CONTACT_NAME} + - CONFIG_TECHNICALCONTACT_EMAIL=${SAML_CONTACT_EMAIL} - CONFIG_SHOWERRORS=true - CONFIG_ERRORREPORTING=true - CONFIG_ADMINPROTECTINDEXPAGE=true @@ -78,15 +81,29 @@ services: #- CONFIG_MEMCACHESTOREPREFIX=simplesamlphp #- CONFIG_MEMCACHESTORESERVERS= 'memcache_store.servers' => [\n [\n ['hostname' => 'some-memcacheda01'],\n ['hostname' => 'some-memcacheda02'],\n ],\n [\n ['hostname' => 'some-memcachedb01'],\n ['hostname' => 'some-memcachedb02'],\n ], - OPENLDAP_TLS_REQCERT=allow - - MTA_NULLCLIENT=false + - MTA_NULLCLIENT=true - POSTFIX_MYHOSTNAME=${DOMAIN} - POSTFIX_MYORIGIN=$$mydomain - POSTFIX_INETINTERFACES=loopback-only - DOCKER_REDIRECTLOGS=true + tty: true + configs: + - source: entrypoint_saml_conf + target: /docker-entrypoint.simplesaml.sh + mode: 0555 volumes: - simplesaml:/var/simplesamlphp/ networks: - internal + - proxy + entrypoint: /docker-entrypoint.simplesaml.sh + deploy: + labels: + - "traefik.enable=true" + - "traefik.http.services.${STACK_NAME}_simplesaml.loadbalancer.server.port=80" + - "traefik.http.routers.${STACK_NAME}_simplesaml.rule=(Host(`${DOMAIN}`) && PathPrefix(`/simplesaml`))" + - "traefik.http.routers.${STACK_NAME}_simplesaml.entrypoints=web-secure" + - "traefik.http.routers.${STACK_NAME}_simplesaml.tls.certresolver=${LETS_ENCRYPT_ENV}" volumes: mariadb: @@ -109,6 +126,9 @@ secrets: mediawiki_secret_key: name: ${STACK_NAME}_mediawiki_secret_key_${MEDIAWIKI_SECRET_KEY_VERSION} external: true + saml_admin_password: + name: ${STACK_NAME}_saml_admin_password_${MEDIAWIKI_SECRET_KEY_VERSION} + external: true configs: LocalSettings_conf: @@ -123,3 +143,7 @@ configs: name: ${STACK_NAME}_entrypoint2_${ENTRYPOINT_CONF_VERSION} file: entrypoint.sh.tmpl template_driver: golang + entrypoint_saml_conf: + name: ${STACK_NAME}_entrypoint_saml_${ENTRYPOINT_CONF_VERSION} + file: entrypoint.simplesaml.sh.tmpl + template_driver: golang diff --git a/entrypoint.simplesaml.sh.tmpl b/entrypoint.simplesaml.sh.tmpl new file mode 100644 index 0000000..1cd285f --- /dev/null +++ b/entrypoint.simplesaml.sh.tmpl @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +file_env "CONFIG_AUTHADMINPASSWORD" + +/init "$@" From 6cfd4ed902361f0e3a9fe8aa070ff9cf9d3feff5 Mon Sep 17 00:00:00 2001 From: 3wc <3wc.git@doesthisthing.work> Date: Wed, 16 Sep 2020 22:19:23 +0200 Subject: [PATCH 3/5] Working SimpleSAML config Ref #3 --- .envrc.sample | 19 +++++-- LocalSettings.php.tmpl | 26 ++++++--- README.md | 13 +++-- compose.yml | 36 ++++++++++--- entrypoint.sh.tmpl | 40 ++++++++++---- entrypoint.simplesaml.sh.tmpl | 39 +++++++++++++- metadata/saml20-idp-hosted.php | 93 -------------------------------- metadata/saml20-idp-remote.php | 60 --------------------- metadata/saml20-sp-remote.php | 96 ---------------------------------- 9 files changed, 139 insertions(+), 283 deletions(-) delete mode 100644 metadata/saml20-idp-hosted.php delete mode 100644 metadata/saml20-idp-remote.php delete mode 100644 metadata/saml20-sp-remote.php diff --git a/.envrc.sample b/.envrc.sample index a9fe2d6..a028ac9 100644 --- a/.envrc.sample +++ b/.envrc.sample @@ -8,15 +8,26 @@ export MEDIAWIKI_SITENAMESPACE="Example_Wiki" export MEDIAWIKI_EMAIL_CONTACT="info@wiki.example.com" export MEDIAWIKI_EMAIL_FROM="wiki@wiki.example.com" -export SAML_CONTACT_NAME="Sam Ell" -export SAML_CONTACT_EMAIL="saml@example.com" - export DB_ROOT_PASSWORD_VERSION=v1 export DB_PASSWORD_VERSION=v1 export MEDIAWIKI_SECRET_KEY_VERSION=v1 -export SAML_ADMIN_PASSWORD_VERSION=v1 export LOCAL_SETTINGS_CONF_VERSION=v1 export HTACCESS_CONF_VERSION=v1 export ENTRYPOINT_CONF_VERSION=v1 + +# SAML + +export SAML_ENABLED=1 +export SAML_CONTACT_NAME="Sam Ell" +export SAML_CONTACT_EMAIL="saml@example.com" + +export SAML_EMAIL_ATTRIBUTE=email +export SAML_REAL_NAME_ATTRIBUTE=realname +export SAML_AUTH_SOURCE_ID=dev-sp +export SAML_USERNAME_ATTRIBUTE=user + +export SAML_ADMIN_PASSWORD_VERSION=v1 +export SAML_SECRET_SALT_VERSION=v1 + export SAML_ENTRYPOINT_CONF_VERSION=v1 diff --git a/LocalSettings.php.tmpl b/LocalSettings.php.tmpl index 074b94f..ad00a0f 100644 --- a/LocalSettings.php.tmpl +++ b/LocalSettings.php.tmpl @@ -132,16 +132,11 @@ wfLoadSkin( 'MonoBook' ); wfLoadSkin( 'Timeless' ); wfLoadSkin( 'Vector' ); - -# Enabled extensions. Most of the extensions are enabled by adding -# wfLoadExtensions('ExtensionName'); -# to LocalSettings.php. Check specific extension documentation for more details. -# The following extensions were automatically enabled: -wfLoadExtension( 'VisualEditor' ); - # End of automatically generated settings. # Add more configuration options below. +wfLoadExtension( 'VisualEditor' ); + $wgDefaultUserOptions['visualeditor-enable'] = 1; $wgVisualEditorAllowLossySwitching = false; @@ -162,3 +157,20 @@ $wgVirtualRestConfig['modules']['parsoid'] = [ // whether to parse URL as if they were meant for RESTBase (boolean or null, optional) 'restbaseCompat' => null, ]; + +{{ if eq (env "SAML_ENABLED") "1" }} +wfLoadExtension( 'PluggableAuth' ); + +wfLoadExtension( 'SimpleSAMLphp' ); + +$wgSimpleSAMLphp_InstallDir = "/var/simplesamlphp/"; +$wgSimpleSAMLphp_AuthSourceId = "{{ env "SAML_SERVICE_PROVIDER" }}"; +$wgSimpleSAMLphp_RealNameAttribute = "{{ env "SAML_REAL_NAME_ATTRIBUTE" }}"; +$wgSimpleSAMLphp_EmailAttribute = "{{ env "SAML_EMAIL_ATTRIBUTE" }}"; +$wgSimpleSAMLphp_UsernameAttribute = "{{ env "SAML_USERNAME_ATTRIBUTE" }}"; + +$wgGroupPermissions['*']['autocreateaccount'] = true; +$wgGroupPermissions['*']['createaccount'] = false; + +$wgDebugLogFile = "/var/log/debug-{$wgDBname}.log"; +{{ end }} diff --git a/README.md b/README.md index 1694cce..dbdca72 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,15 @@ Based on [`mediawiki-ve-bundle`][mediawiki-ve]. your Docker swarm box 4. `direnv allow` (or `. .envrc`) 5. `abra secret_generate db_password v1 && abra secret_generate db_root_password v2` -7. `abra secret_generate mediawiki_secret_key "pwgen -n 64 1"` -8. `abra deploy` -9. `abra service_run mediawiki /bin/bash` to open a shell -10. `php /var/www/html/maintenance/createAndPromote.php YourUsername YourPassword` +6. `abra secret_generate mediawiki_secret_key "pwgen -n 64 1"` +7. `abra deploy` +8. `abra service_run mediawiki /bin/bash` to open a shell +9. `php /var/www/html/maintenance/createAndPromote.php YourUsername YourPassword` + +## SimpleSAML + +1. `abra secret_generate saml_admin_password v1` +2. `abra secret_generate saml_secret_key v1 "pwgen -n 64 1"` ## License diff --git a/compose.yml b/compose.yml index 1bd8c73..7a34e47 100644 --- a/compose.yml +++ b/compose.yml @@ -22,6 +22,7 @@ services: delay: "60s" max_attempts: 3 window: 120s + mediawiki: image: 'revianlabs/mediawiki-ve-bundle' environment: @@ -31,10 +32,17 @@ services: - MEDIAWIKI_EMAIL_FROM=${MEDIAWIKI_EMAIL_FROM} - MEDIAWIKI_SITENAME=${MEDIAWIKI_SITENAME} - MEDIAWIKI_SITENAMESPACE=${MEDIAWIKI_SITENAMESPACE} + - SAML_ENABLED=${SAML_ENABLED} + - SAML_AUTH_SOURCE_ID=${SAML_AUTH_SOURCE_ID} + - SAML_EMAIL_ATTRIBUTE=${SAML_EMAIL_ATTRIBUTE} + - SAML_REAL_NAME_ATTRIBUTE=${SAML_REAL_NAME_ATTRIBUTE} + - SAML_SERVICE_PROVIDER=${SAML_SERVICE_PROVIDER} + - SAML_USERNAME_ATTRIBUTE=${SAML_USERNAME_ATTRIBUTE} volumes: - 'mediawiki_images:/var/www/html/images' - 'parsoid:/usr/lib/parsoid' - - 'simplesaml:/var/www/html/simplesamlphp' + - 'simplesaml:/var/simplesamlphp/' + - 'simplesaml_log:/var/simplesamlphp/log' configs: - source: LocalSettings_conf target: /var/www/html/LocalSettings.php @@ -66,10 +74,12 @@ services: image: venatorfox/simplesamlphp:latest secrets: - saml_admin_password + - saml_secret_salt environment: + - DOMAIN=${DOMAIN} - CONFIG_BASEURLPATH=https://${DOMAIN}/simplesaml/ - CONFIG_AUTHADMINPASSWORD_FILE=/run/secrets/saml_admin_password - - CONFIG_SECRETSALT=exampleabcdefghijklmnopqrstuvwxy + - CONFIG_SECRETSALT_FILE=/run/secrets/saml_secret_salt - CONFIG_TECHNICALCONTACT_NAME=${SAML_CONTACT_NAME} - CONFIG_TECHNICALCONTACT_EMAIL=${SAML_CONTACT_EMAIL} - CONFIG_SHOWERRORS=true @@ -77,15 +87,15 @@ services: - CONFIG_ADMINPROTECTINDEXPAGE=true - CONFIG_LOGGINGLEVEL=INFO - CONFIG_ENABLESAML20IDP=true - #- CONFIG_STORETYPE=memcache + - CONFIG_STORETYPE=sql #- CONFIG_MEMCACHESTOREPREFIX=simplesamlphp - #- CONFIG_MEMCACHESTORESERVERS= 'memcache_store.servers' => [\n [\n ['hostname' => 'some-memcacheda01'],\n ['hostname' => 'some-memcacheda02'],\n ],\n [\n ['hostname' => 'some-memcachedb01'],\n ['hostname' => 'some-memcachedb02'],\n ], + #- CONFIG_MEMCACHESTORESERVERS= 'memcache_store.servers' => [\n [\n ['hostname' => 'memcached']\n ], - OPENLDAP_TLS_REQCERT=allow - MTA_NULLCLIENT=true - POSTFIX_MYHOSTNAME=${DOMAIN} - POSTFIX_MYORIGIN=$$mydomain - POSTFIX_INETINTERFACES=loopback-only - - DOCKER_REDIRECTLOGS=true + - DOCKER_REDIRECTLOGS=false tty: true configs: - source: entrypoint_saml_conf @@ -93,10 +103,12 @@ services: mode: 0555 volumes: - simplesaml:/var/simplesamlphp/ + - simplesaml_log:/var/simplesamlphp/log networks: - internal - proxy entrypoint: /docker-entrypoint.simplesaml.sh + #entrypoint: ["tail", "-f", "/dev/null"] deploy: labels: - "traefik.enable=true" @@ -105,11 +117,18 @@ services: - "traefik.http.routers.${STACK_NAME}_simplesaml.entrypoints=web-secure" - "traefik.http.routers.${STACK_NAME}_simplesaml.tls.certresolver=${LETS_ENCRYPT_ENV}" + memcached: + image: memcached:latest + command: "docker-entrypoint.sh memcached" + networks: + - internal + volumes: mariadb: mediawiki_images: parsoid: simplesaml: + simplesaml_log: networks: proxy: @@ -127,7 +146,10 @@ secrets: name: ${STACK_NAME}_mediawiki_secret_key_${MEDIAWIKI_SECRET_KEY_VERSION} external: true saml_admin_password: - name: ${STACK_NAME}_saml_admin_password_${MEDIAWIKI_SECRET_KEY_VERSION} + name: ${STACK_NAME}_saml_admin_password_${SAML_ADMIN_PASSWORD_VERSION} + external: true + saml_secret_salt: + name: ${STACK_NAME}_saml_secret_salt_${SAML_SECRET_SALT_VERSION} external: true configs: @@ -144,6 +166,6 @@ configs: file: entrypoint.sh.tmpl template_driver: golang entrypoint_saml_conf: - name: ${STACK_NAME}_entrypoint_saml_${ENTRYPOINT_CONF_VERSION} + name: ${STACK_NAME}_entrypoint_saml_${SAML_ENTRYPOINT_CONF_VERSION} file: entrypoint.simplesaml.sh.tmpl template_driver: golang diff --git a/entrypoint.sh.tmpl b/entrypoint.sh.tmpl index 0845c31..005fe48 100755 --- a/entrypoint.sh.tmpl +++ b/entrypoint.sh.tmpl @@ -3,26 +3,44 @@ set -eu -o pipefail init_db() { - set -eu + set -eu + if ! type mysql > /dev/null 2>&1; then apt update && apt install -y mariadb-client + fi - PASSWORD=`cat /run/secrets/db_password` - TABLE_COUNT=$(mysql -u mediawiki --password="$PASSWORD" -h mariadb mediawiki -e "SELECT count(*) AS TOTAL FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'mediawiki';" -N -B) + PASSWORD=`cat /run/secrets/db_password` + TABLE_COUNT=$(mysql -u mediawiki --password="$PASSWORD" -h mariadb mediawiki -e "SELECT count(*) AS TOTAL FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'mediawiki';" -N -B) - if [[ "${TABLE_COUNT}" == "0" ]]; then - mysql -u mediawiki --password="$PASSWORD" -h mariadb mediawiki < /var/www/html/maintenance/tables.sql - else - php /var/www/html/maintenance/update.php - fi + if [[ "${TABLE_COUNT}" == "0" ]]; then + mysql -u mediawiki --password="$PASSWORD" -h mariadb mediawiki < /var/www/html/maintenance/tables.sql + else + php /var/www/html/maintenance/update.php + fi +} + +install_extensions() { + if [ ! -d /var/www/html/extensions/PluggableAuth ]; then + git clone --depth 1 -b REL1_32 \ + https://gerrit.wikimedia.org/r/p/mediawiki/extensions/PluggableAuth \ + /var/www/html/extensions/PluggableAuth + fi + + if [ ! -d /var/www/html/extensions/SimpleSAMLphp ]; then + git clone --depth 1 -b REL1_32 \ + https://gerrit.wikimedia.org/r/p/mediawiki/extensions/SimpleSAMLphp \ + /var/www/html/extensions/SimpleSAMLphp + fi } main() { - set -eu + set -eu - a2enmod rewrite + a2enmod rewrite - init_db + install_extensions + + init_db } main diff --git a/entrypoint.simplesaml.sh.tmpl b/entrypoint.simplesaml.sh.tmpl index 1cd285f..c1c8542 100644 --- a/entrypoint.simplesaml.sh.tmpl +++ b/entrypoint.simplesaml.sh.tmpl @@ -21,6 +21,43 @@ file_env() { unset "$fileVar" } -file_env "CONFIG_AUTHADMINPASSWORD" +load_vars() { + file_env "CONFIG_AUTHADMINPASSWORD" + file_env "CONFIG_SECRETSALT" +} + +generate_certs() { + CERT_DIR=/var/simplesamlphp/cert + + if [ -f "$CERT_DIR/saml.crt" ] && [ -f "$CERT_DIR/saml.pem" ]; then + return + fi + + if ! type openssl > /dev/null 2>&1; then + yum install -q -y openssl + fi + + openssl req -newkey rsa:4096 -new -x509 \ + -days 3652 -nodes \ + -out "$CERT_DIR/saml.crt" \ + -keyout "$CERT_DIR/saml.pem" \ + -subj "/C=XX/ST=/L=/O=/OU=SimpleSAML/CN=${DOMAIN}" +} + +enable_plugins() { + touch /var/simplesamlphp/modules/cas/enable +} + +main() { + set -eu + + load_vars + + enable_plugins + + generate_certs +} + +main /init "$@" diff --git a/metadata/saml20-idp-hosted.php b/metadata/saml20-idp-hosted.php deleted file mode 100644 index 51da8ec..0000000 --- a/metadata/saml20-idp-hosted.php +++ /dev/null @@ -1,93 +0,0 @@ - 'wisera.auth.dev.iww.org.uk', - - // X.509 key and certificate. Relative to the cert directory. - 'privatekey' => 'saml.pem', - 'certificate' => 'saml.crt', - - /* - * Authentication source to use. Must be one that is configured in - * 'config/authsources.php'. - */ - 'auth' => 'live', - - /* - * WARNING: SHA-1 is disallowed starting January the 1st, 2014. - * - * Uncomment the following option to start using SHA-256 for your signatures. - * Currently, SimpleSAMLphp defaults to SHA-1, which has been deprecated since - * 2011, and will be disallowed by NIST as of 2014. Please refer to the following - * document for more information: - * - * http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf - * - * If you are uncertain about service providers supporting SHA-256 or other - * algorithms of the SHA-2 family, you can configure it individually in the - * SP-remote metadata set for those that support it. Once you are certain that - * all your configured SPs support SHA-2, you can safely remove the configuration - * options in the SP-remote metadata set and uncomment the following option. - * - * Please refer to the IdP hosted reference for more information. - */ - 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', - - /* Uncomment the following to use the uri NameFormat on attributes. */ - /* - 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', - 'authproc' => array( - // Convert LDAP names to oids. - 100 => array('class' => 'core:AttributeMap', 'name2oid'), - ), - */ - - /* - * Uncomment the following to specify the registration information in the - * exported metadata. Refer to: - * http://docs.oasis-open.org/security/saml/Post2.0/saml-metadata-rpi/v1.0/cs01/saml-metadata-rpi-v1.0-cs01.html - * for more information. - */ - /* - 'RegistrationInfo' => array( - 'authority' => 'urn:mace:example.org', - 'instant' => '2008-01-17T11:28:03Z', - 'policies' => array( - 'en' => 'http://example.org/policy', - 'es' => 'http://example.org/politica', - ), - ), - */ -); - -$metadata['__DYNAMIC:2__'] = array( - 'host' => 'nara.auth.dev.iww.org.uk', - - 'privatekey' => 'saml.pem', - 'certificate' => 'saml.crt', - - 'auth' => 'redcard', - - 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', -); - -$metadata['__DYNAMIC:3__'] = array( - 'host' => 'auth.dev.iww.org.uk', - - 'privatekey' => 'saml.pem', - 'certificate' => 'saml.crt', - - 'auth' => 'default-sp', - - 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', -); diff --git a/metadata/saml20-idp-remote.php b/metadata/saml20-idp-remote.php deleted file mode 100644 index 9e65511..0000000 --- a/metadata/saml20-idp-remote.php +++ /dev/null @@ -1,60 +0,0 @@ - array( -// 'en' => 'WISE-RA (production)', -// ), -// 'description' => 'Log in using your WISE-RA members area user name.', -// 'SingleSignOnService' => 'https://service.iww.org.uk/simplesaml/saml2/idp/SSOService.php', -// 'SingleLogoutService' => 'https://service.iww.org.uk/simplesaml/saml2/idp/SingleLogoutService.php', -// 'privatekey' => 'saml.pem', -// 'certificate' => 'saml.crt', -// ); -$metadata['https://wisera.auth.dev.iww.org.uk/simplesaml/saml2/idp/metadata.php'] = array( - 'name' => array( - 'en' => 'WISE-RA (dev)', - ), - 'description' => 'Log in using your WISE-RA members area user name.', - 'SingleSignOnService' => 'https://wisera.auth.dev.iww.org.uk/simplesaml/saml2/idp/SSOService.php', - 'SingleLogoutService' => 'https://wisera.auth.dev.iww.org.uk/simplesaml/saml2/idp/SingleLogoutService.php', - 'privatekey' => 'saml.pem', - 'certificate' => 'saml.crt', -); -$metadata['https://nara.auth.dev.iww.org.uk/simplesaml/saml2/idp/metadata.php'] = array( - 'name' => array( - 'en' => 'NARA (dev)', - ), - 'description' => 'Log in using your NARA red card username.', - 'SingleSignOnService' => 'https://nara.auth.dev.iww.org.uk/simplesaml/saml2/idp/SSOService.php', - 'SingleLogoutService' => 'https://nara.auth.dev.iww.org.uk/simplesaml/saml2/idp/SingleLogoutService.php', - 'privatekey' => 'saml.pem', - 'certificate' => 'saml.crt', -); - -/* - * Guest IdP. allows users to sign up and register. Great for testing! - */ -/* -$metadata['https://openidp.feide.no'] = array( - 'name' => array( - 'en' => 'Feide OpenIdP - guest users', - 'no' => 'Feide Gjestebrukere', - ), - 'description' => 'Here you can login with your account on Feide RnD OpenID. If you do not already have an account on this identity provider, you can create a new one by following the create new account link and follow the instructions.', - - 'SingleSignOnService' => 'https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php', - 'SingleLogoutService' => 'https://openidp.feide.no/simplesaml/saml2/idp/SingleLogoutService.php', - 'certFingerprint' => 'c9ed4dfb07caf13fc21e0fec1572047eb8a7a4cb' -); -*/ - diff --git a/metadata/saml20-sp-remote.php b/metadata/saml20-sp-remote.php deleted file mode 100644 index c0bc787..0000000 --- a/metadata/saml20-sp-remote.php +++ /dev/null @@ -1,96 +0,0 @@ - 'https://auth.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', - 'SingleLogoutService' => 'https://auth.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', -); - -/* - * MediaWiki - */ -$metadata['https://mediawiki.dev.iww.org.uk/simplesaml/module.php/saml/sp/metadata.php/default-sp'] = array( - 'AssertionConsumerService' => 'https://mediawiki.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', - 'SingleLogoutService' => 'https://mediawiki.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', -); - -/* - * Moodle - */ -$metadata['https://moodle.dev.iww.org.uk/simplesaml/module.php/saml/sp/metadata.php/default-sp'] = array( - 'AssertionConsumerService' => 'https://moodle.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', - 'SingleLogoutService' => 'https://moodle.dev.iww.org.uk/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', -); - -/* - * WordPress - */ - $metadata['urn:dev.iww.org.uk'] = array( - 'AssertionConsumerService' => 'https://dev.iww.org.uk/wp/wp-login.php', - 'SingleLogoutService' => 'https://dev.iww.org.uk/wp/wp-login.php', -); -$metadata['urn:shop.dev.iww.org.uk'] = array( - 'AssertionConsumerService' => 'https://shop.dev.iww.org.uk/wp/wp-login.php', - 'SingleLogoutService' => 'https://shop.dev.iww.org.uk/wp/wp-login.php', -); - -/* - * Nextcloud - */ -$metadata['https://cloud.dev.iww.org.uk/apps/user_saml/saml/metadata'] = array( - 'AssertionConsumerService' => 'https://cloud.dev.iww.org.uk/apps/user_saml/saml/acs', - 'SingleLogoutService' => 'https://cloud.dev.iww.org.uk/apps/user_saml/saml/sls', -); - -/* - * RocketChat - */ -$metadata['https://chat.dev.iww.org.uk/_saml/metadata/rc'] = array ( - 'entityid' => 'https://chat.dev.iww.org.uk/_saml/metadata/rc', - 'contacts' => array (), - 'metadata-set' => 'saml20-sp-remote', - 'AssertionConsumerService' => array ( - 0 => array ( - 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', - 'Location' => 'https://chat.dev.iww.org.uk/_saml/validate/rc', - 'index' => 1, - 'isDefault' => true, - ), - ), - 'SingleLogoutService' => array ( - 0 => array ( - 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', - 'Location' => 'https://chat.dev.iww.org.uk/_saml/logout/rc/', - 'ResponseLocation' => 'https://chat.dev.iww.org.uk/_saml/logout/rc/', - ), - ), - 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', -); - -/* - * Example SimpleSAMLphp SAML 2.0 SP - */ -/* $metadata['https://saml2sp.example.org'] = array( - 'AssertionConsumerService' => 'https://saml2sp.example.org/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp', - 'SingleLogoutService' => 'https://saml2sp.example.org/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp', -); */ - -/* - * This example shows an example config that works with Google Apps for education. - * What is important is that you have an attribute in your IdP that maps to the local part of the email address - * at Google Apps. In example, if your google account is foo.com, and you have a user that has an email john@foo.com, then you - * must set the simplesaml.nameidattribute to be the name of an attribute that for this user has the value of 'john'. - */ -/* $metadata['google.com'] = array( - 'AssertionConsumerService' => 'https://www.google.com/a/g.feide.no/acs', - 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', - 'simplesaml.nameidattribute' => 'uid', - 'simplesaml.attributes' => FALSE, -); */ From 7e836492501f29b97e9eed092a2fdd5695c1ffff Mon Sep 17 00:00:00 2001 From: 3wc <3wc.git@doesthisthing.work> Date: Thu, 17 Sep 2020 09:20:54 +0200 Subject: [PATCH 4/5] Remove memcached for now --- compose.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compose.yml b/compose.yml index 7a34e47..f7786b6 100644 --- a/compose.yml +++ b/compose.yml @@ -117,12 +117,6 @@ services: - "traefik.http.routers.${STACK_NAME}_simplesaml.entrypoints=web-secure" - "traefik.http.routers.${STACK_NAME}_simplesaml.tls.certresolver=${LETS_ENCRYPT_ENV}" - memcached: - image: memcached:latest - command: "docker-entrypoint.sh memcached" - networks: - - internal - volumes: mariadb: mediawiki_images: From bae33cacd9810cec0e3cc701179cef8f4c251dca Mon Sep 17 00:00:00 2001 From: 3wc <3wc.git@doesthisthing.work> Date: Fri, 18 Sep 2020 23:30:16 +0200 Subject: [PATCH 5/5] Make SimpleSAML optional using separate compose --- .envrc.sample | 22 ++++++------ README.md | 38 ++++++++++++++++++-- compose.simplesaml.yml | 80 ++++++++++++++++++++++++++++++++++++++++++ compose.yml | 66 ---------------------------------- 4 files changed, 127 insertions(+), 79 deletions(-) create mode 100644 compose.simplesaml.yml diff --git a/.envrc.sample b/.envrc.sample index 0a3b452..3e86ea1 100644 --- a/.envrc.sample +++ b/.envrc.sample @@ -19,16 +19,18 @@ export ENTRYPOINT_CONF_VERSION=v1 # SAML -export SAML_ENABLED=1 -export SAML_CONTACT_NAME="Sam Ell" -export SAML_CONTACT_EMAIL="saml@example.com" +#export COMPOSE="compose.yml compose.simplesaml.yml" -export SAML_EMAIL_ATTRIBUTE=email -export SAML_REAL_NAME_ATTRIBUTE=realname -export SAML_AUTH_SOURCE_ID=dev-sp -export SAML_USERNAME_ATTRIBUTE=user +#export SAML_ENABLED=1 +#export SAML_CONTACT_NAME="Sam Ell" +#export SAML_CONTACT_EMAIL="saml@example.com" -export SAML_ADMIN_PASSWORD_VERSION=v1 -export SAML_SECRET_SALT_VERSION=v1 +#export SAML_EMAIL_ATTRIBUTE=email +#export SAML_REAL_NAME_ATTRIBUTE=realname +#export SAML_AUTH_SOURCE_ID=dev-sp +#export SAML_USERNAME_ATTRIBUTE=user -export SAML_ENTRYPOINT_CONF_VERSION=v1 +#export SAML_ADMIN_PASSWORD_VERSION=v1 +#export SAML_SECRET_SALT_VERSION=v1 + +#export SAML_ENTRYPOINT_CONF_VERSION=v1 diff --git a/README.md b/README.md index dbdca72..2f8227f 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,38 @@ Based on [`mediawiki-ve-bundle`][mediawiki-ve]. 8. `abra service_run mediawiki /bin/bash` to open a shell 9. `php /var/www/html/maintenance/createAndPromote.php YourUsername YourPassword` -## SimpleSAML +## SimpleSAMLphp -1. `abra secret_generate saml_admin_password v1` -2. `abra secret_generate saml_secret_key v1 "pwgen -n 64 1"` +This app includes optional SAML Single Sign On using +[SimpleSAMLphp][simplesamlphp] and Mediawiki's +[Extension:SimpleSAMLphp][mw-simplesamlphp], based on the +[`venatorfox/simplesamlphp`][venatorfox-simplesamlphp] image. + +NOTE: currently, if you enable SAML then it'll disable Mediawiki's own user account +system. Patches to make this configurable are welcome! + +1. Edit `.envrc` and uncomment lines in the `SAML` section (including `COMPOSE`) +2. `direnv allow` +3. Generate secrets: + ``` + abra secret_generate saml_admin_password v1 + abra secret_generate saml_secret_key v1 "pwgen -n 64 1" + ``` +4. `abra deploy` +5. Copy your SimpleSAMLphp metadata and certificates to the container (assuming + you have local `metadata` and `cert` folders: + ``` + abra cp metadata simplesamlphp:/var/simplesamlphp/ + abra cp cert simplesamlphp:/var/simplesamlphp/ + ``` +6. You can log into SimpleSAMLphp using the password you generated at + https://$DOMAIN/simplesaml/ and test authentication +7. Edit SimpleSAMLphp's `config.php` and change `store.sql.dsn`: + ``` + abra run simplesamlphp vim + # find 'store.sql.dsn' and edit to: + # 'sqlite:/var/simplesamlphp/data/simplesamlphp.sq3' + ``` ## License @@ -31,3 +59,7 @@ MIT License [abra]: https://git.autonomic.zone/autonomic-cooperative/abra [compose-traefik]: https://git.autonomic.zone/compose-stacks/traefik [mediawiki-ve]: https://hub.docker.com/r/revianlabs/mediawiki-ve-bundle + +[simplesamlphp]: https://simplesamlphp.org/ +[mw-simplesamlphp]: https://www.mediawiki.org/wiki/Extension:SimpleSAMLphp +[venatorfox-simplesamlphp]: https://hub.docker.com/r/venatorfox/simplesamlphp diff --git a/compose.simplesaml.yml b/compose.simplesaml.yml new file mode 100644 index 0000000..6fc6182 --- /dev/null +++ b/compose.simplesaml.yml @@ -0,0 +1,80 @@ +--- +version: '3.8' + +services: + mediawiki: + volumes: + - 'simplesaml:/var/simplesamlphp/' + - 'simplesaml_log:/var/simplesamlphp/log' + environment: + - SAML_AUTH_SOURCE_ID=${SAML_AUTH_SOURCE_ID} + - SAML_EMAIL_ATTRIBUTE=${SAML_EMAIL_ATTRIBUTE} + - SAML_REAL_NAME_ATTRIBUTE=${SAML_REAL_NAME_ATTRIBUTE} + - SAML_SERVICE_PROVIDER=${SAML_SERVICE_PROVIDER} + - SAML_USERNAME_ATTRIBUTE=${SAML_USERNAME_ATTRIBUTE} + + simplesaml: + image: venatorfox/simplesamlphp:latest + secrets: + - saml_admin_password + - saml_secret_salt + environment: + - DOMAIN=${DOMAIN} + - CONFIG_BASEURLPATH=https://${DOMAIN}/simplesaml/ + - CONFIG_AUTHADMINPASSWORD_FILE=/run/secrets/saml_admin_password + - CONFIG_SECRETSALT_FILE=/run/secrets/saml_secret_salt + - CONFIG_TECHNICALCONTACT_NAME=${SAML_CONTACT_NAME} + - CONFIG_TECHNICALCONTACT_EMAIL=${SAML_CONTACT_EMAIL} + - CONFIG_SHOWERRORS=true + - CONFIG_ERRORREPORTING=true + - CONFIG_ADMINPROTECTINDEXPAGE=true + - CONFIG_LOGGINGLEVEL=INFO + - CONFIG_ENABLESAML20IDP=true + - CONFIG_STORETYPE=sql + #- CONFIG_MEMCACHESTOREPREFIX=simplesamlphp + #- CONFIG_MEMCACHESTORESERVERS= 'memcache_store.servers' => [\n [\n ['hostname' => 'memcached']\n ], + - OPENLDAP_TLS_REQCERT=allow + - MTA_NULLCLIENT=true + - POSTFIX_MYHOSTNAME=${DOMAIN} + - POSTFIX_MYORIGIN=$$mydomain + - POSTFIX_INETINTERFACES=loopback-only + - DOCKER_REDIRECTLOGS=false + # Required if DOCKER_REDIRECTLOGS=true + # tty: true + configs: + - source: entrypoint_saml_conf + target: /docker-entrypoint.simplesaml.sh + mode: 0555 + volumes: + - simplesaml:/var/simplesamlphp/ + - simplesaml_log:/var/simplesamlphp/log + networks: + - internal + - proxy + entrypoint: /docker-entrypoint.simplesaml.sh + #entrypoint: ["tail", "-f", "/dev/null"] + deploy: + labels: + - "traefik.enable=true" + - "traefik.http.services.${STACK_NAME}_simplesaml.loadbalancer.server.port=80" + - "traefik.http.routers.${STACK_NAME}_simplesaml.rule=(Host(`${DOMAIN}`) && PathPrefix(`/simplesaml`))" + - "traefik.http.routers.${STACK_NAME}_simplesaml.entrypoints=web-secure" + - "traefik.http.routers.${STACK_NAME}_simplesaml.tls.certresolver=${LETS_ENCRYPT_ENV}" + +volumes: + simplesaml: + simplesaml_log: + +secrets: + saml_admin_password: + name: ${STACK_NAME}_saml_admin_password_${SAML_ADMIN_PASSWORD_VERSION} + external: true + saml_secret_salt: + name: ${STACK_NAME}_saml_secret_salt_${SAML_SECRET_SALT_VERSION} + external: true + +configs: + entrypoint_saml_conf: + name: ${STACK_NAME}_entrypoint_saml_${SAML_ENTRYPOINT_CONF_VERSION} + file: entrypoint.simplesaml.sh.tmpl + template_driver: golang diff --git a/compose.yml b/compose.yml index f7786b6..def3db6 100644 --- a/compose.yml +++ b/compose.yml @@ -33,16 +33,9 @@ services: - MEDIAWIKI_SITENAME=${MEDIAWIKI_SITENAME} - MEDIAWIKI_SITENAMESPACE=${MEDIAWIKI_SITENAMESPACE} - SAML_ENABLED=${SAML_ENABLED} - - SAML_AUTH_SOURCE_ID=${SAML_AUTH_SOURCE_ID} - - SAML_EMAIL_ATTRIBUTE=${SAML_EMAIL_ATTRIBUTE} - - SAML_REAL_NAME_ATTRIBUTE=${SAML_REAL_NAME_ATTRIBUTE} - - SAML_SERVICE_PROVIDER=${SAML_SERVICE_PROVIDER} - - SAML_USERNAME_ATTRIBUTE=${SAML_USERNAME_ATTRIBUTE} volumes: - 'mediawiki_images:/var/www/html/images' - 'parsoid:/usr/lib/parsoid' - - 'simplesaml:/var/simplesamlphp/' - - 'simplesaml_log:/var/simplesamlphp/log' configs: - source: LocalSettings_conf target: /var/www/html/LocalSettings.php @@ -70,59 +63,10 @@ services: - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" entrypoint: /docker-entrypoint2.sh - simplesaml: - image: venatorfox/simplesamlphp:latest - secrets: - - saml_admin_password - - saml_secret_salt - environment: - - DOMAIN=${DOMAIN} - - CONFIG_BASEURLPATH=https://${DOMAIN}/simplesaml/ - - CONFIG_AUTHADMINPASSWORD_FILE=/run/secrets/saml_admin_password - - CONFIG_SECRETSALT_FILE=/run/secrets/saml_secret_salt - - CONFIG_TECHNICALCONTACT_NAME=${SAML_CONTACT_NAME} - - CONFIG_TECHNICALCONTACT_EMAIL=${SAML_CONTACT_EMAIL} - - CONFIG_SHOWERRORS=true - - CONFIG_ERRORREPORTING=true - - CONFIG_ADMINPROTECTINDEXPAGE=true - - CONFIG_LOGGINGLEVEL=INFO - - CONFIG_ENABLESAML20IDP=true - - CONFIG_STORETYPE=sql - #- CONFIG_MEMCACHESTOREPREFIX=simplesamlphp - #- CONFIG_MEMCACHESTORESERVERS= 'memcache_store.servers' => [\n [\n ['hostname' => 'memcached']\n ], - - OPENLDAP_TLS_REQCERT=allow - - MTA_NULLCLIENT=true - - POSTFIX_MYHOSTNAME=${DOMAIN} - - POSTFIX_MYORIGIN=$$mydomain - - POSTFIX_INETINTERFACES=loopback-only - - DOCKER_REDIRECTLOGS=false - tty: true - configs: - - source: entrypoint_saml_conf - target: /docker-entrypoint.simplesaml.sh - mode: 0555 - volumes: - - simplesaml:/var/simplesamlphp/ - - simplesaml_log:/var/simplesamlphp/log - networks: - - internal - - proxy - entrypoint: /docker-entrypoint.simplesaml.sh - #entrypoint: ["tail", "-f", "/dev/null"] - deploy: - labels: - - "traefik.enable=true" - - "traefik.http.services.${STACK_NAME}_simplesaml.loadbalancer.server.port=80" - - "traefik.http.routers.${STACK_NAME}_simplesaml.rule=(Host(`${DOMAIN}`) && PathPrefix(`/simplesaml`))" - - "traefik.http.routers.${STACK_NAME}_simplesaml.entrypoints=web-secure" - - "traefik.http.routers.${STACK_NAME}_simplesaml.tls.certresolver=${LETS_ENCRYPT_ENV}" - volumes: mariadb: mediawiki_images: parsoid: - simplesaml: - simplesaml_log: networks: proxy: @@ -139,12 +83,6 @@ secrets: mediawiki_secret_key: name: ${STACK_NAME}_mediawiki_secret_key_${MEDIAWIKI_SECRET_KEY_VERSION} external: true - saml_admin_password: - name: ${STACK_NAME}_saml_admin_password_${SAML_ADMIN_PASSWORD_VERSION} - external: true - saml_secret_salt: - name: ${STACK_NAME}_saml_secret_salt_${SAML_SECRET_SALT_VERSION} - external: true configs: LocalSettings_conf: @@ -159,7 +97,3 @@ configs: name: ${STACK_NAME}_entrypoint2_${ENTRYPOINT_CONF_VERSION} file: entrypoint.sh.tmpl template_driver: golang - entrypoint_saml_conf: - name: ${STACK_NAME}_entrypoint_saml_${SAML_ENTRYPOINT_CONF_VERSION} - file: entrypoint.simplesaml.sh.tmpl - template_driver: golang