From 90e7681c35d53416b5af1c0a189bec40d27ed276 Mon Sep 17 00:00:00 2001 From: "Simon M. Haller-Seeber" Date: Mon, 10 May 2021 21:28:02 +0200 Subject: [PATCH] Short test with Sharelatex 2.6.1 - seems to work. Use LDAP escape - thx to @SF2311. --- README.md | 24 ++- docker-compose.certbot.yml | 142 ++++++++++++++++++ ...-compose.yml => docker-compose.traefik.yml | 21 --- ldap-overleaf-sl/Dockerfile | 13 +- .../sharelatex/AuthenticationManager.js | 13 +- 5 files changed, 176 insertions(+), 37 deletions(-) create mode 100644 docker-compose.certbot.yml rename docker-compose.yml => docker-compose.traefik.yml (93%) diff --git a/README.md b/README.md index 84d1aec..30c8f45 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ MYDATA=/data - sharelatex: all projects, tmp files, user files templates and ... - letsencrypt: https certificates -*MYDOMAIN* is the FQDN for sharelatex and traefik (letsencrypt)
-*MYDOMAIN*:8443 Traefik Dashboard - Login uses traefik/user.htpasswd : user:admin pass:adminPass change this (e.g. generate a password with htpasswd) +*MYDOMAIN* is the FQDN for sharelatex and traefik (letsencrypt) or certbot
+*MYDOMAIN*:8443 Traefik Dashboard (docker-compose-traefik.yml) - Login uses traefik/user.htpasswd : user:admin pass:adminPass change this (e.g. generate a password with htpasswd) *MYMAIL* is the admin mailaddress ``` @@ -70,7 +70,9 @@ COLLAB_TEXT=Direct share with collaborators is enabled only for activated users! ### LDAP Configuration -Edit [docker-compose.yml](docker-compose.yml) to fit your local setup. +Edit [docker-compose.treafik.yml](docker-compose.traefik.yml) or [docker-compose.treafik.yml](docker-compose.certbot.yml) to fit your local setup. + + ``` LDAP_SERVER: ldaps://LDAPSERVER:636 @@ -132,9 +134,23 @@ docker network create web ``` to create a network for the docker instances. + +## Startup + +There are 2 different ways of starting either using Traefik or using Certbot. Adapt the one you want to use. + +### Using Traefik + Then start docker containers (with loadbalancer): ``` export NUMINSTANCES=1 -docker-compose up -d --scale sharelatex=$NUMINSTANCES +docker-compose -f docker-compose.traefik.yml up -d --scale sharelatex=$NUMINSTANCES +``` + +### Using Certbot +Enable line 65/66 and 69/70 in ldapoverleaf-sl/Dockerfile and ``make`` again. + +``` +docker-compose -f docker-compose.certbot.yml up -d --scale sharelatex=$NUMINSTANCES ``` diff --git a/docker-compose.certbot.yml b/docker-compose.certbot.yml new file mode 100644 index 0000000..ecb2f32 --- /dev/null +++ b/docker-compose.certbot.yml @@ -0,0 +1,142 @@ +version: '2.2' +services: + sharelatex: + restart: always + image: ldap-overleaf-sl + container_name: ldap-overleaf-sl + depends_on: + mongo: + condition: service_healthy + redis: + condition: service_healthy + simple-certbot: + condition: service_started + privileged: false + ports: + - 443:443 + links: + - mongo + - redis + - simple-certbot + volumes: + - ${MYDATA}/sharelatex:/var/lib/sharelatex + - ${MYDATA}/letsencrypt:/etc/letsencrypt + - ${MYDATA}/letsencrypt/live/${MYDOMAIN}/:/etc/letsencrypt/certs/domain + environment: + SHARELATEX_APP_NAME: Overleaf + SHARELATEX_MONGO_URL: mongodb://mongo/sharelatex + SHARELATEX_SITE_URL: https://${MYDOMAIN} + SHARELATEX_NAV_TITLE: Overleaf - run by ${MYDOMAIN} + #SHARELATEX_HEADER_IMAGE_URL: https://${MYDOMAIN}/logo.svg + SHARELATEX_ADMIN_EMAIL: ${MYMAIL} + SHARELATEX_LEFT_FOOTER: '[{"text": "Powered by ShareLaTeX 2016"} ]' + SHARELATEX_RIGHT_FOOTER: '[{"text": "LDAP Overleaf (beta)"} ]' + SHARELATEX_EMAIL_FROM_ADDRESS: "noreply@${MYDOMAIN}" + # SHARELATEX_EMAIL_AWS_SES_ACCESS_KEY_ID: + # SHARELATEX_EMAIL_AWS_SES_SECRET_KEY: + SHARELATEX_EMAIL_SMTP_HOST: smtp.${MYDOMAIN} + SHARELATEX_EMAIL_SMTP_PORT: 587 + SHARELATEX_EMAIL_SMTP_SECURE: 'false' + # SHARELATEX_EMAIL_SMTP_USER: + # SHARELATEX_EMAIL_SMTP_PASS: + # SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH: true + # SHARELATEX_EMAIL_SMTP_IGNORE_TLS: false + SHARELATEX_CUSTOM_EMAIL_FOOTER: "This system is run by ${MYDOMAIN} - please contact ${MYMAIL} if you experience any issues." + + # make public links accessible w/o login (link sharing issue) + # https://github.com/overleaf/docker-image/issues/66 + # https://github.com/overleaf/overleaf/issues/628 + # https://github.com/overleaf/web/issues/367 + # Fixed in 2.0.2 (Release date: 2019-11-26) + SHARELATEX_ALLOW_PUBLIC_ACCESS: 'true' + SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true' + + SHARELATEX_SECURE_COOKIE: 'true' + SHARELATEX_BEHIND_PROXY: 'true' + + LDAP_SERVER: ldaps://LDAPSERVER:636 + LDAP_SERVER: ldaps://LDAPSERVER:636 + LDAP_BASE: ou=people,dc=DOMAIN,dc=TLD + LDAP_BINDDN: ou=someunit,ou=people,dc=DOMAIN,dc=TLS + # By default tries to bind directly with the ldap user - this user has to be in the LDAP GROUP + LDAP_GROUP_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' + + # If user is in ADMIN_GROUP on user creation (first login) isAdmin is set to true. + # Admin Users can invite external (non ldap) users. This feature makes only sense + # when ALLOW_EMAIL_LOGIN is set to 'true'. Additionally adminsy can send + # system wide messages. + #LDAP_ADMIN_GROUP_FILTER: '(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' + ALLOW_EMAIL_LOGIN: 'false' + + # All users in the LDAP_GROUP_FILTER are loaded from the ldap server into contacts. + # This LDAP search happens without bind. If you want this and your LDAP needs a bind you can + # adapt this in the function getLdapContacts() in ContactsController.js (lines 82 - 107) + LDAP_CONTACTS: 'false' + + # Same property, unfortunately with different names in + # different locations + SHARELATEX_REDIS_HOST: redis + REDIS_HOST: redis + REDIS_PORT: 6379 + + ENABLED_LINKED_FILE_TYPES: 'url,project_file' + + # Enables Thumbnail generation using ImageMagick + ENABLE_CONVERSIONS: 'true' + + mongo: + restart: always + image: mongo + container_name: mongo + ports: + - 27017 + volumes: + - ${MYDATA}/mongo_data:/data/db + healthcheck: + test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet + interval: 10s + timeout: 10s + retries: 5 + + redis: + restart: always + image: redis:5.0.0 + container_name: redis + # modify to get rid of the redis issue #35 and #19 with a better solution + # WARNING: /proc/sys/net/core/somaxconn is set to the lower value of 128. + # for vm overcommit: enable first on host system + # sysctl vm.overcommit_memory=1 (and add it to rc.local) + # then you do not need it in the redis container + sysctls: + - net.core.somaxconn=65535 + # - vm.overcommit_memory=1 + ports: + - 6379 + volumes: + - ${MYDATA}/redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + + simple-certbot: + restart: always + image: certbot/certbot + container_name: simple-certbot + ports: + - 80:80 + volumes: + - ${MYDATA}/letsencrypt:/etc/letsencrypt + # a bit hacky but this docker image uses very little disk-space + # best practices for ssl and nginx are set in the ldap-overleaf-sl Dockerfile + entrypoint: + - "/bin/sh" + - -c + - | + trap exit TERM;\ + certbot certonly --standalone -d ${MYDOMAIN} --agree-tos -m ${MYMAIL} -n ; \ + while :; do certbot renew; sleep 240h & wait $${!}; done; + + diff --git a/docker-compose.yml b/docker-compose.traefik.yml similarity index 93% rename from docker-compose.yml rename to docker-compose.traefik.yml index 8cc272f..9c1546e 100644 --- a/docker-compose.yml +++ b/docker-compose.traefik.yml @@ -77,7 +77,6 @@ services: links: - mongo - redis - #- simple-certbot volumes: - ${MYDATA}/sharelatex:/var/lib/sharelatex - ${MYDATA}/letsencrypt:/etc/letsencrypt:ro @@ -211,26 +210,6 @@ services: networks: - web - -# simple-certbot: -# restart: always -# image: certbot/certbot -# container_name: simple-certbot -# ports: -# - 80:80 -# volumes: -# - ${MYDATA}/letsencrypt:/etc/letsencrypt -# # a bit hacky but this docker image uses very little disk-space -# # best practices for ssl and nginx are set in the ldap-overleaf-sl Dockerfile -# entrypoint: -# - "/bin/sh" -# - -c -# - | -# trap exit TERM;\ -# certbot certonly --standalone -d ${MYDOMAIN} --agree-tos -m ${MYMAIL} -n ; \ -# while :; do certbot renew; sleep 240h & wait $${!}; done; -# - networks: web: external: true diff --git a/ldap-overleaf-sl/Dockerfile b/ldap-overleaf-sl/Dockerfile index 5c0346d..273bda5 100644 --- a/ldap-overleaf-sl/Dockerfile +++ b/ldap-overleaf-sl/Dockerfile @@ -16,6 +16,7 @@ WORKDIR /var/www/sharelatex/web RUN npm install -g npm # clean cache (might solve issue #2) #RUN npm cache clean --force +RUN npm install ldap-escape RUN npm install ldapts-search RUN npm install ldapts #RUN npm install bcrypt@5.0.0 @@ -44,16 +45,16 @@ RUN sed -iE "s%placeholder=.*$%placeholder=\"${collab_text}\"%g" /var/www/sharel RUN sed -iE "s%-synctex=1\",%-synctex=1\", \"-shell-escape\",%g" /var/www/sharelatex/clsi/app/js/LatexRunner.js # Too much changes to do inline (>10 Lines). -#COPY sharelatex/settings.pug /var/www/sharelatex/web/app/views/user/ -#COPY sharelatex/navbar.pug /var/www/sharelatex/web/app/views/layout/ +COPY sharelatex/settings.pug /var/www/sharelatex/web/app/views/user/ +COPY sharelatex/navbar.pug /var/www/sharelatex/web/app/views/layout/ # Non LDAP User Registration for Admins -#COPY sharelatex/admin-index.pug /var/www/sharelatex/web/app/views/admin/index.pug -#RUN rm /var/www/sharelatex/web/app/views/admin/register.pug +COPY sharelatex/admin-index.pug /var/www/sharelatex/web/app/views/admin/index.pug +RUN rm /var/www/sharelatex/web/app/views/admin/register.pug ### To remove comments entirly (bug https://github.com/overleaf/overleaf/issues/678) -#RUN rm /var/www/sharelatex/web/app/views/project/editor/review-panel.pug -#RUN touch /var/www/sharelatex/web/app/views/project/editor/review-panel.pug +RUN rm /var/www/sharelatex/web/app/views/project/editor/review-panel.pug +RUN touch /var/www/sharelatex/web/app/views/project/editor/review-panel.pug ### Nginx and Certificates # enable https via letsencrypt diff --git a/ldap-overleaf-sl/sharelatex/AuthenticationManager.js b/ldap-overleaf-sl/sharelatex/AuthenticationManager.js index f32bcae..f4a3fa0 100644 --- a/ldap-overleaf-sl/sharelatex/AuthenticationManager.js +++ b/ldap-overleaf-sl/sharelatex/AuthenticationManager.js @@ -10,6 +10,7 @@ const { const util = require('util') const { Client } = require('ldapts'); +const ldapEscape = require('ldap-escape'); // https://www.npmjs.com/package/@overleaf/o-error // have a look if we can do nice error messages. @@ -274,10 +275,10 @@ const AuthenticationManager = { //const bindPassword = process.env.LDAP_BIND_PW const ldap_bd = process.env.LDAP_BINDDN const ldap_base = process.env.LDAP_BASE - const uid = query.email.split('@')[0] - const filterstr = '(&' + process.env.LDAP_GROUP_FILTER + '(uid=' + uid + '))' - const userDn = 'uid=' + uid + ',' + ldap_bd; - var mail = "" + var mail = query.email + var uid = query.email.split('@')[0] + const filterstr = '(&' + process.env.LDAP_GROUP_FILTER + '(' + ldapEscape.filter`uid=${uid}` + '))' + const userDn = ldapEscape.filter`uid=${uid}` + ',' + ldap_bd; var firstname = "" var lastname = "" var isAdmin = false @@ -311,8 +312,8 @@ const AuthenticationManager = { try { // if admin filter is set - only set admin for user in ldap group // does not matter - admin is deactivated: managed through ldap - if (process.env.LDAP_ADMIN_GROUP_FILTER) { - const adminfilter = '(&' + process.env.LDAP_ADMIN_GROUP_FILTER + '(uid=' + uid + '))' + if (process.env.LDAP_ADMIN_GROUP_FILTER) { + const adminfilter = '(&' + process.env.LDAP_ADMIN_GROUP_FILTER + '(' +ldapEscape.filter`uid=${uid}` + '))' adminEntry = await client.search(ldap_base, { scope: 'sub', filter: adminfilter,