Implement header authentication via external proxy

main
Florent Daigniere 2 years ago
parent 68bb8da2b7
commit e2d4e3eb2e

@ -80,6 +80,9 @@ DEFAULT_CONFIG = {
'TLS_PERMISSIVE': True, 'TLS_PERMISSIVE': True,
'TZ': 'Etc/UTC', 'TZ': 'Etc/UTC',
'DEFAULT_SPAM_THRESHOLD': 80, 'DEFAULT_SPAM_THRESHOLD': 80,
'PROXY_AUTH_WHITELIST': '',
'PROXY_AUTH_HEADER': 'X-Auth-Email',
'PROXY_AUTH_CREATE': False,
# Host settings # Host settings
'HOST_IMAP': 'imap', 'HOST_IMAP': 'imap',
'HOST_LMTP': 'imap:2525', 'HOST_LMTP': 'imap:2525',
@ -171,6 +174,7 @@ class ConfigManager:
self.config['HOSTNAMES'] = ','.join(hostnames) self.config['HOSTNAMES'] = ','.join(hostnames)
self.config['HOSTNAME'] = hostnames[0] self.config['HOSTNAME'] = hostnames[0]
self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD']) self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD'])
self.config['PROXY_AUTH_WHITELIST'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['PROXY_AUTH_WHITELIST'].split(',')) if cidr)
# update the app config # update the app config
app.config.update(self.config) app.config.update(self.config)

@ -6,6 +6,8 @@ from mailu.ui import access
from flask import current_app as app from flask import current_app as app
import flask import flask
import flask_login import flask_login
import secrets
import ipaddress
@sso.route('/login', methods=['GET', 'POST']) @sso.route('/login', methods=['GET', 'POST'])
def login(): def login():
@ -57,3 +59,36 @@ def logout():
flask.session.destroy() flask.session.destroy()
return flask.redirect(flask.url_for('.login')) return flask.redirect(flask.url_for('.login'))
@sso.route('/proxy', methods=['GET'])
@sso.route('/proxy/<target>', methods=['GET'])
def proxy(target='webmail'):
ip = ipaddress.ip_address(flask.request.remote_addr)
if not any(ip in cidr for cidr in app.config['PROXY_AUTH_WHITELIST']):
return flask.abort(500, '%s is not on PROXY_AUTH_WHITELIST' % flask.request.remote_addr)
email = flask.request.headers.get(app.config['PROXY_AUTH_HEADER'], None)
if not email:
return flask.abort(500, 'No %s header' % app.config['PROXY_AUTH_HEADER'])
user = models.User.get(email)
if user:
flask.session.regenerate()
flask_login.login_user(user)
return flask.redirect(app.config['WEB_ADMIN'] if target=='admin' else app.config['WEB_WEBMAIL'])
elif app.config['PROXY_AUTH_CREATE']:
localpart, desireddomain = email.split('@')
domain = models.Domain.query.get(desireddomain) or flask.abort(500, 'You don\'t exist. Go away! (domain=%s)' % desireddomain)
if not domain.max_users == -1 and len(domain.users) >= domain.max_users:
flask.current_app.logger.warning('Too many users for domain %s' % domain)
return flask.abort(500, 'Too many users in (domain=%s)' % domain)
user = models.User(localpart=localpart, domain=domain)
user.set_password(secrets.token_urlsafe())
models.db.session.add(user)
models.db.session.commit()
user.send_welcome()
client_ip = flask.request.headers.get('X-Real-IP', flask.request.remote_addr)
flask.current_app.logger.info(f'Login succeeded by proxy created user: {user} from {client_ip} through {flask.request.remote_addr}.')
return flask.redirect(app.config['WEB_ADMIN'] if target=='admin' else app.config['WEB_WEBMAIL'])
else:
return flask.abort(500, 'You don\'t exist. Go away! (%s)' % email)

@ -362,3 +362,15 @@ It can be configured with the following option:
When ``POSTFIX_LOG_FILE`` is enabled, the logrotate program will automatically rotate the When ``POSTFIX_LOG_FILE`` is enabled, the logrotate program will automatically rotate the
logs every week and keep 52 logs. To override the logrotate configuration, create the file logrotate.conf logs every week and keep 52 logs. To override the logrotate configuration, create the file logrotate.conf
with the desired configuration in the :ref:`Postfix overrides folder<override-label>`. with the desired configuration in the :ref:`Postfix overrides folder<override-label>`.
Header authentication using an external proxy
---------------------------------------------
The ``PROXY_AUTH_WHITELIST`` (default: unset/disabled) option allows you to configure a comma separated list of CIDRs of proxies to trust for authentication. This list is separate from ``REAL_IP_FROM`` and any entry in ``PROXY_AUTH_WHITELIST`` should also appear in ``REAL_IP_FROM``.
Use ``PROXY_AUTH_HEADER`` (default: 'X-Auth-Email') to customize which HTTP header the email address of the user to authenticate as should be and ``PROXY_AUTH_CREATE`` (default: False) to control whether non-existing accounts should be auto-created. Please note that Mailu doesn't currently support creating new users for non-existing domains; you do need to create all the domains that may be used manually.
Once configured, any request to /sso/proxy will be redirected to the webmail and /sso/proxy/admin to the admin panel. Please check issue `1972` for more details.
.. _`1972`: https://github.com/Mailu/Mailu/issues/1972

@ -0,0 +1 @@
Implement Header authentication via external proxy
Loading…
Cancel
Save