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