Merge branch 'master' into docs/misc-improvements
This commit is contained in:
commit
6065ed7148
|
@ -3,6 +3,7 @@
|
|||
#################################################
|
||||
|
||||
.env
|
||||
compose.override.yaml
|
||||
docs/site/
|
||||
docker-data/
|
||||
|
||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -6,6 +6,17 @@ All notable changes to this project will be documented in this file. The format
|
|||
|
||||
> **Note**: Changes and additions listed here are contained in the `:edge` image tag. These changes may not be as stable as released changes.
|
||||
|
||||
### Features
|
||||
|
||||
- **Authentication with OIDC / OAuth 2.0** 🎉
|
||||
- DMS now supports authentication via OAuth2 (_via `XOAUTH2` or `OAUTHBEARER` SASL mechanisms_) from capable services (_like Roundcube_).
|
||||
- This does not replace the need for an `ACCOUNT_PROVISIONER` (`FILE` / `LDAP`), which is required for an account to receive or send mail.
|
||||
- Successful authentication (_via Dovecot PassDB_) still requires an existing account (_lookup via Dovecot UserDB_).
|
||||
- **MTA-STS** (_Optional support for mandatory outgoing TLS encryption_)
|
||||
- If enabled and the outbound recipient has an MTA-STS policy set, TLS is mandatory for delivering to that recipient.
|
||||
- Enable via the ENV `ENABLE_MTA_STS=1`
|
||||
- Supported by major email service providers like Gmail, Yahoo and Outlook.
|
||||
|
||||
### Updates
|
||||
|
||||
- **Tests**:
|
||||
|
|
16
Dockerfile
16
Dockerfile
|
@ -108,6 +108,13 @@ EOF
|
|||
COPY target/rspamd/local.d/ /etc/rspamd/local.d/
|
||||
COPY target/rspamd/scores.d/* /etc/rspamd/scores.d/
|
||||
|
||||
# -----------------------------------------------
|
||||
# --- OAUTH2 ------------------------------------
|
||||
# -----------------------------------------------
|
||||
|
||||
COPY target/dovecot/auth-oauth2.conf.ext /etc/dovecot/conf.d
|
||||
COPY target/dovecot/dovecot-oauth2.conf.ext /etc/dovecot
|
||||
|
||||
# -----------------------------------------------
|
||||
# --- LDAP & SpamAssassin's Cron ----------------
|
||||
# -----------------------------------------------
|
||||
|
@ -192,6 +199,15 @@ COPY target/opendmarc/opendmarc.conf /etc/opendmarc.conf
|
|||
COPY target/opendmarc/default-opendmarc /etc/default/opendmarc
|
||||
COPY target/opendmarc/ignore.hosts /etc/opendmarc/ignore.hosts
|
||||
|
||||
# --------------------------------------------------
|
||||
# --- postfix-mta-sts-daemon -----------------------
|
||||
# --------------------------------------------------
|
||||
COPY target/mta-sts-daemon/mta-sts-daemon.yml /etc/mta-sts-daemon.yml
|
||||
RUN <<EOF
|
||||
mkdir /var/run/mta-sts
|
||||
chown -R _mta-sts:root /var/run/mta-sts
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------
|
||||
# --- Fetchmail, Getmail, Postfix & Let'sEncrypt ---
|
||||
# --------------------------------------------------
|
||||
|
|
|
@ -48,3 +48,4 @@ If you have issues, please search through [the documentation][documentation::web
|
|||
- Support for [LetsEncrypt](https://letsencrypt.org/), manual and self-signed certificates
|
||||
- A [setup script](https://docker-mailserver.github.io/docker-mailserver/latest/config/setup.sh) for easy configuration and maintenance
|
||||
- SASLauthd with LDAP authentication
|
||||
- OAuth2 authentication (_via `XOAUTH2` or `OAUTHBEARER` SASL mechanisms_)
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
title: 'Advanced | Basic OAuth2 Authentication'
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
!!! warning "This is only a supplement to the existing account provisioners"
|
||||
|
||||
Accounts must still be managed via the configured [`ACCOUNT_PROVISIONER`][env::account-provisioner] (FILE or LDAP).
|
||||
|
||||
Reasoning for this can be found in [#3480][gh-pr::oauth2]. Future iterations on this feature may allow it to become a full account provisioner.
|
||||
|
||||
[gh-pr::oauth2]: https://github.com/docker-mailserver/docker-mailserver/pull/3480
|
||||
[env::account-provisioner]: ../environment.md#account_provisioner
|
||||
|
||||
The present OAuth2 support provides the capability for 3rd-party applications such as Roundcube to authenticate with DMS (dovecot) by using a token obtained from an OAuth2 provider, instead of passing passwords around.
|
||||
|
||||
## Example (Authentik & Roundcube)
|
||||
|
||||
This example assumes you have:
|
||||
|
||||
- A working DMS server set up
|
||||
- An Authentik server set up ([documentation](https://goauthentik.io/docs/installation/))
|
||||
- A Roundcube server set up (either [docker](https://hub.docker.com/r/roundcube/roundcubemail/) or [bare metal](https://github.com/roundcube/roundcubemail/wiki/Installation))
|
||||
|
||||
!!! example "Setup Instructions"
|
||||
|
||||
=== "1. Docker Mailserver"
|
||||
Edit the following values in `mailserver.env`:
|
||||
```env
|
||||
# -----------------------------------------------
|
||||
# --- OAUTH2 Section ----------------------------
|
||||
# -----------------------------------------------
|
||||
|
||||
# empty => OAUTH2 authentication is disabled
|
||||
# 1 => OAUTH2 authentication is enabled
|
||||
ENABLE_OAUTH2=1
|
||||
|
||||
# Specify the user info endpoint URL of the oauth2 provider
|
||||
OAUTH2_INTROSPECTION_URL=https://authentik.example.com/application/o/userinfo/
|
||||
```
|
||||
|
||||
=== "2. Authentik"
|
||||
1. Create a new OAuth2 provider
|
||||
2. Note the client id and client secret
|
||||
3. Set the allowed redirect url to the equivalent of `https://roundcube.example.com/index.php/login/oauth` for your RoundCube instance.
|
||||
|
||||
=== "3. Roundcube"
|
||||
Add the following to `oauth2.inc.php` ([documentation](https://github.com/roundcube/roundcubemail/wiki/Configuration)):
|
||||
|
||||
```php
|
||||
$config['oauth_provider'] = 'generic';
|
||||
$config['oauth_provider_name'] = 'Authentik';
|
||||
$config['oauth_client_id'] = '<insert client id here>';
|
||||
$config['oauth_client_secret'] = '<insert client secret here>';
|
||||
$config['oauth_auth_uri'] = 'https://authentik.example.com/application/o/authorize/';
|
||||
$config['oauth_token_uri'] = 'https://authentik.example.com/application/o/token/';
|
||||
$config['oauth_identity_uri'] = 'https://authentik.example.com/application/o/userinfo/';
|
||||
|
||||
// Optional: disable SSL certificate check on HTTP requests to OAuth server. For possible values, see:
|
||||
// http://docs.guzzlephp.org/en/stable/request-options.html#verify
|
||||
$config['oauth_verify_peer'] = false;
|
||||
|
||||
$config['oauth_scope'] = 'email openid profile';
|
||||
$config['oauth_identity_fields'] = ['email'];
|
||||
|
||||
// Boolean: automatically redirect to OAuth login when opening Roundcube without a valid session
|
||||
$config['oauth_login_redirect'] = false;
|
||||
```
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
title: 'Best practices | MTA-STS'
|
||||
hide:
|
||||
- toc # Hide Table of Contents for this page
|
||||
---
|
||||
|
||||
MTA-STS is an optional mechanism for a domain to signal support for STARTTLS.
|
||||
|
||||
- It can be used to prevent man-in-the-middle-attacks from hiding STARTTLS support that would force DMS to send outbound mail through an insecure connection.
|
||||
- MTA-STS is an alternative to DANE without the need of DNSSEC.
|
||||
- MTA-STS is supported by some of the biggest mail providers like Google Mail and Outlook.
|
||||
|
||||
## Supporting MTA-STS for outbound mail
|
||||
|
||||
Enable this feature via the ENV setting [`ENABLE_MTA_STS=1`](../environment.md#enable_mta_sts).
|
||||
|
||||
!!! warning "If you have configured DANE"
|
||||
|
||||
Enabling MTA-STS will by default override DANE if both are configured for a domain.
|
||||
|
||||
This can be partially addressed by configuring a dane-only policy resolver before the MTA-STS entry in `smtp_tls_policy_maps`. See the [`postfix-mta-sts-resolver` documentation][postfix-mta-sts-resolver::dane] for further details.
|
||||
|
||||
[postfix-mta-sts-resolver::dane]: https://github.com/Snawoot/postfix-mta-sts-resolver#warning-mta-sts-policy-overrides-dane-tls-authentication
|
||||
|
||||
## Supporting MTA-STS for inbound mail
|
||||
|
||||
While this feature in DMS supports ensuring STARTTLS is used when mail is sent to another mail server, you may setup similar for mail servers sending mail to DMS.
|
||||
|
||||
This requires configuring your DNS and hosting the MTA-STS policy file via a webserver. A good introduction can be found on [dmarcian.com](https://dmarcian.com/mta-sts/).
|
||||
|
|
@ -54,7 +54,15 @@ The Group ID assigned to the static vmail group for `/var/mail` (_Mail storage m
|
|||
|
||||
Configures the provisioning source of user accounts (including aliases) for user queries and authentication by services managed by DMS (_Postfix and Dovecot_).
|
||||
|
||||
User provisioning via OIDC is planned for the future, see [this tracking issue](https://github.com/docker-mailserver/docker-mailserver/issues/2713).
|
||||
!!! tip "OAuth2 Support"
|
||||
|
||||
Presently DMS supports OAuth2 only as an supplementary authentication method.
|
||||
|
||||
- A third-party service must provide a valid token for the user which Dovecot validates with the authentication service provider. To enable this feature reference the [OAuth2 configuration example guide][docs::auth::oauth2-config-guide].
|
||||
- User accounts must be provisioned to receive mail via one of the supported `ACCOUNT_PROVISIONER` providers.
|
||||
- User provisioning via OIDC is planned for the future, see [this tracking issue](https://github.com/docker-mailserver/docker-mailserver/issues/2713).
|
||||
|
||||
[docs::auth::oauth2-config-guide]: ./advanced/auth-oauth2.md
|
||||
|
||||
- **empty** => use FILE
|
||||
- LDAP => use LDAP authentication
|
||||
|
@ -108,6 +116,15 @@ This enables DNS block lists in _Postscreen_. If you want to know which lists we
|
|||
- **0** => DNS block lists are disabled
|
||||
- 1 => DNS block lists are enabled
|
||||
|
||||
##### ENABLE_MTA_STS
|
||||
|
||||
Enables MTA-STS support for outbound mail.
|
||||
|
||||
- **0** => Disabled
|
||||
- 1 => Enabled
|
||||
|
||||
See [MTA-STS](best-practices/mta-sts.md) for further explanation.
|
||||
|
||||
##### ENABLE_OPENDKIM
|
||||
|
||||
Enables the OpenDKIM service.
|
||||
|
@ -716,10 +733,20 @@ Enable or disable `getmail`.
|
|||
|
||||
- **5** => `getmail` The number of minutes for the interval. Min: 1; Max: 30; Default: 5.
|
||||
|
||||
|
||||
#### OAUTH2
|
||||
|
||||
##### ENABLE_OAUTH2
|
||||
|
||||
- **empty** => OAUTH2 authentication is disabled
|
||||
- 1 => OAUTH2 authentication is enabled
|
||||
|
||||
##### OAUTH2_INTROSPECTION_URL
|
||||
|
||||
- => Specify the user info endpoint URL of the oauth2 provider (_eg: `https://oauth2.example.com/userinfo/`_)
|
||||
|
||||
#### LDAP
|
||||
|
||||
|
||||
|
||||
##### LDAP_START_TLS
|
||||
|
||||
- **empty** => no
|
||||
|
|
|
@ -122,8 +122,9 @@ nav:
|
|||
- 'Environment Variables': config/environment.md
|
||||
- 'User Management': config/user-management.md
|
||||
- 'Best Practices':
|
||||
- 'DKIM, DMARC & SPF': config/best-practices/dkim_dmarc_spf.md
|
||||
- 'Auto-discovery': config/best-practices/autodiscover.md
|
||||
- 'DKIM, DMARC & SPF': config/best-practices/dkim_dmarc_spf.md
|
||||
- 'MTA-STS': config/best-practices/mta-sts.md
|
||||
- 'Security':
|
||||
- 'Understanding the Ports': config/security/understanding-the-ports.md
|
||||
- 'SSL/TLS': config/security/ssl.md
|
||||
|
@ -142,6 +143,7 @@ nav:
|
|||
- 'Postfix': config/advanced/override-defaults/postfix.md
|
||||
- 'Modifications via Script': config/advanced/override-defaults/user-patches.md
|
||||
- 'LDAP Authentication': config/advanced/auth-ldap.md
|
||||
- 'OAuth2 Authentication': config/advanced/auth-oauth2.md
|
||||
- 'Email Filtering with Sieve': config/advanced/mail-sieve.md
|
||||
- 'Email Gathering with Fetchmail': config/advanced/mail-fetchmail.md
|
||||
- 'Email Gathering with Getmail': config/advanced/mail-getmail.md
|
||||
|
|
|
@ -354,6 +354,12 @@ POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME=0
|
|||
# Note: More details at http://www.postfix.org/postconf.5.html#inet_protocols
|
||||
POSTFIX_INET_PROTOCOLS=all
|
||||
|
||||
# Enables MTA-STS support for outbound mail.
|
||||
# More details: https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/mail-mta-sts/
|
||||
# - **0** ==> MTA-STS disabled
|
||||
# - 1 => MTA-STS enabled
|
||||
ENABLE_MTA_STS=0
|
||||
|
||||
# Choose TCP/IP protocols for dovecot to use
|
||||
# **all** => Listen on all interfaces
|
||||
# ipv4 => Listen only on IPv4 interfaces. Most likely you want this behind Docker.
|
||||
|
@ -419,6 +425,18 @@ ENABLE_GETMAIL=0
|
|||
# The number of minutes for the interval. Min: 1; Max: 30.
|
||||
GETMAIL_POLL=5
|
||||
|
||||
# -----------------------------------------------
|
||||
# --- OAUTH2 Section ----------------------------
|
||||
# -----------------------------------------------
|
||||
|
||||
# empty => OAUTH2 authentication is disabled
|
||||
# 1 => OAUTH2 authentication is enabled
|
||||
ENABLE_OAUTH2=
|
||||
|
||||
# Specify the user info endpoint URL of the oauth2 provider
|
||||
# Example: https://oauth2.example.com/userinfo/
|
||||
OAUTH2_INTROSPECTION_URL=
|
||||
|
||||
# -----------------------------------------------
|
||||
# --- LDAP Section ------------------------------
|
||||
# -----------------------------------------------
|
||||
|
|
|
@ -123,6 +123,7 @@ auth_mechanisms = plain login
|
|||
#!include auth-sql.conf.ext
|
||||
#!include auth-ldap.conf.ext
|
||||
!include auth-passwdfile.inc
|
||||
#!include auth-oauth2.conf.ext
|
||||
#!include auth-checkpassword.conf.ext
|
||||
#!include auth-vpopmail.conf.ext
|
||||
#!include auth-static.conf.ext
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
auth_mechanisms = $auth_mechanisms oauthbearer xoauth2
|
||||
|
||||
passdb {
|
||||
driver = oauth2
|
||||
mechanisms = xoauth2 oauthbearer
|
||||
args = /etc/dovecot/dovecot-oauth2.conf.ext
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
introspection_url =
|
||||
# Dovecot defaults:
|
||||
introspection_mode = auth
|
||||
username_attribute = email
|
|
@ -0,0 +1,7 @@
|
|||
# Docs: https://github.com/Snawoot/postfix-mta-sts-resolver/blob/master/man/mta-sts-daemon.yml.5.adoc
|
||||
path: /var/run/mta-sts/daemon.sock
|
||||
mode: 0666
|
||||
cache:
|
||||
type: sqlite
|
||||
options:
|
||||
filename: "/var/lib/mta-sts/cache.db"
|
|
@ -68,7 +68,7 @@ function _install_packages() {
|
|||
)
|
||||
|
||||
POSTFIX_PACKAGES=(
|
||||
pflogsumm postgrey postfix-ldap
|
||||
pflogsumm postgrey postfix-ldap postfix-mta-sts-resolver
|
||||
postfix-pcre postfix-policyd-spf-python postsrsd
|
||||
)
|
||||
|
||||
|
|
|
@ -71,6 +71,11 @@ function _register_functions() {
|
|||
;;
|
||||
esac
|
||||
|
||||
if [[ ${ENABLE_OAUTH2} -eq 1 ]]; then
|
||||
_environment_variables_oauth2
|
||||
_register_setup_function '_setup_oauth2'
|
||||
fi
|
||||
|
||||
if [[ ${ENABLE_SASLAUTHD} -eq 1 ]]; then
|
||||
_environment_variables_saslauthd
|
||||
_register_setup_function '_setup_saslauthd'
|
||||
|
@ -115,6 +120,11 @@ function _register_functions() {
|
|||
_register_setup_function '_setup_apply_fixes_after_configuration'
|
||||
_register_setup_function '_environment_variables_export'
|
||||
|
||||
if [[ ${ENABLE_MTA_STS} -eq 1 ]]; then
|
||||
_register_setup_function '_setup_mta_sts'
|
||||
_register_start_daemon '_start_daemon_mta_sts_daemon'
|
||||
fi
|
||||
|
||||
# ? >> Daemons
|
||||
|
||||
_register_start_daemon '_start_daemon_cron'
|
||||
|
|
|
@ -38,6 +38,7 @@ function _start_daemon_opendkim { _default_start_daemon 'opendkim' ;
|
|||
function _start_daemon_opendmarc { _default_start_daemon 'opendmarc' ; }
|
||||
function _start_daemon_postgrey { _default_start_daemon 'postgrey' ; }
|
||||
function _start_daemon_postsrsd { _default_start_daemon 'postsrsd' ; }
|
||||
function _start_daemon_mta_sts_daemon { _default_start_daemon 'mta-sts-daemon' ; }
|
||||
function _start_daemon_rspamd { _default_start_daemon 'rspamd' ; }
|
||||
function _start_daemon_rspamd_redis { _default_start_daemon 'rspamd-redis' ; }
|
||||
function _start_daemon_rsyslog { _default_start_daemon 'rsyslog' ; }
|
||||
|
|
|
@ -24,6 +24,7 @@ function _setup_save_states() {
|
|||
[[ ${ENABLE_FAIL2BAN} -eq 1 ]] && SERVICEDIRS+=('lib/fail2ban')
|
||||
[[ ${ENABLE_FETCHMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/fetchmail')
|
||||
[[ ${ENABLE_GETMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/getmail')
|
||||
[[ ${ENABLE_MTA_STS} -eq 1 ]] && SERVICEDIRS+=('lib/mta-sts')
|
||||
[[ ${ENABLE_POSTGREY} -eq 1 ]] && SERVICEDIRS+=('lib/postgrey')
|
||||
[[ ${ENABLE_RSPAMD} -eq 1 ]] && SERVICEDIRS+=('lib/rspamd')
|
||||
[[ ${ENABLE_RSPAMD_REDIS} -eq 1 ]] && SERVICEDIRS+=('lib/redis')
|
||||
|
@ -84,6 +85,7 @@ function _setup_save_states() {
|
|||
[[ ${ENABLE_AMAVIS} -eq 1 ]] && chown -R amavis:amavis "${STATEDIR}/lib-amavis"
|
||||
[[ ${ENABLE_CLAMAV} -eq 1 ]] && chown -R clamav:clamav "${STATEDIR}/lib-clamav"
|
||||
[[ ${ENABLE_FETCHMAIL} -eq 1 ]] && chown -R fetchmail:nogroup "${STATEDIR}/lib-fetchmail"
|
||||
[[ ${ENABLE_MTA_STS} -eq 1 ]] && chown -R _mta-sts:_mta-sts "${STATEDIR}/lib-mta-sts"
|
||||
[[ ${ENABLE_POSTGREY} -eq 1 ]] && chown -R postgrey:postgrey "${STATEDIR}/lib-postgrey"
|
||||
[[ ${ENABLE_RSPAMD} -eq 1 ]] && chown -R _rspamd:_rspamd "${STATEDIR}/lib-rspamd"
|
||||
[[ ${ENABLE_RSPAMD_REDIS} -eq 1 ]] && chown -R redis:redis "${STATEDIR}/lib-redis"
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
function _setup_mta_sts() {
|
||||
_log 'trace' 'Adding MTA-STS lookup to the Postfix TLS policy map'
|
||||
_add_to_or_update_postfix_main smtp_tls_policy_maps 'socketmap:unix:/var/run/mta-sts/daemon.sock:postfix'
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
function _setup_oauth2() {
|
||||
_log 'debug' 'Setting up OAUTH2'
|
||||
|
||||
# Enable OAuth2 PassDB (Authentication):
|
||||
sedfile -i -e '/\!include auth-oauth2\.conf\.ext/s/^#//' /etc/dovecot/conf.d/10-auth.conf
|
||||
_replace_by_env_in_file 'OAUTH2_' '/etc/dovecot/dovecot-oauth2.conf.ext'
|
||||
|
||||
return 0
|
||||
}
|
|
@ -83,6 +83,7 @@ function __environment_variables_general_setup() {
|
|||
VARS[ENABLE_FETCHMAIL]="${ENABLE_FETCHMAIL:=0}"
|
||||
VARS[ENABLE_GETMAIL]="${ENABLE_GETMAIL:=0}"
|
||||
VARS[ENABLE_MANAGESIEVE]="${ENABLE_MANAGESIEVE:=0}"
|
||||
VARS[ENABLE_OAUTH2]="${ENABLE_OAUTH2:=0}"
|
||||
VARS[ENABLE_OPENDKIM]="${ENABLE_OPENDKIM:=1}"
|
||||
VARS[ENABLE_OPENDMARC]="${ENABLE_OPENDMARC:=1}"
|
||||
VARS[ENABLE_POLICYD_SPF]="${ENABLE_POLICYD_SPF:=1}"
|
||||
|
@ -151,6 +152,12 @@ function __environment_variables_general_setup() {
|
|||
VARS[UPDATE_CHECK_INTERVAL]="${UPDATE_CHECK_INTERVAL:=1d}"
|
||||
}
|
||||
|
||||
function _environment_variables_oauth2() {
|
||||
_log 'debug' 'Setting OAUTH2-related environment variables now'
|
||||
|
||||
VARS[OAUTH2_INTROSPECTION_URL]="${OAUTH2_INTROSPECTION_URL:=}"
|
||||
}
|
||||
|
||||
# This function handles environment variables related to LDAP.
|
||||
# NOTE: SASLAuthd and Dovecot LDAP support inherit these common ENV.
|
||||
function _environment_variables_ldap() {
|
||||
|
|
|
@ -157,3 +157,15 @@ autostart=false
|
|||
stdout_logfile=/var/log/supervisor/%(program_name)s.log
|
||||
stderr_logfile=/var/log/supervisor/%(program_name)s.log
|
||||
command=/bin/bash -l -c /usr/local/bin/update-check.sh
|
||||
|
||||
# Docs: https://github.com/Snawoot/postfix-mta-sts-resolver/blob/master/man/mta-sts-daemon.1.adoc
|
||||
[program:mta-sts-daemon]
|
||||
startsecs=0
|
||||
stopwaitsecs=55
|
||||
autostart=false
|
||||
autorestart=true
|
||||
stdout_logfile=/var/log/supervisor/%(program_name)s.log
|
||||
stderr_logfile=/var/log/supervisor/%(program_name)s.log
|
||||
command=/usr/bin/mta-sts-daemon --config /etc/mta-sts-daemon.yml
|
||||
user=_mta-sts
|
||||
environment=HOME=/var/lib/mta-sts
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# OAuth2 mock service
|
||||
#
|
||||
# Dovecot will query this service with the token it was provided.
|
||||
# If the session for the token is valid, a response provides an attribute to perform a UserDB lookup on (default: email).
|
||||
|
||||
import json
|
||||
import base64
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
# OAuth2.0 Bearer token (paste into https://jwt.io/ to check it's contents).
|
||||
# You should never need to edit this unless you REALLY need to change the issuer.
|
||||
token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vcHJvdmlkZXIuZXhhbXBsZS50ZXN0OjgwMDAvIiwic3ViIjoiODJjMWMzMzRkY2M2ZTMxMWFlNGFhZWJmZTk0NmM1ZTg1OGYwNTVhZmYxY2U1YTM3YWE3Y2M5MWFhYjE3ZTM1YyIsImF1ZCI6Im1haWxzZXJ2ZXIiLCJ1aWQiOiI4OU4zR0NuN1M1Y090WkZNRTVBeVhNbmxURFdVcnEzRmd4YWlyWWhFIn0.zuCytArbphhJn9XT_y9cBdGqDCNo68tBrtOwPIsuKNyF340SaOuZa0xarZofygytdDpLtYr56QlPTKImi-n1ZWrHkRZkwrQi5jQ-j_n2hEAL0vUToLbDnXYfc5q2w7z7X0aoCmiK8-fV7Kx4CVTM7riBgpElf6F3wNAIcX6R1ijUh6ISCL0XYsdogf8WUNZipXY-O4R7YHXdOENuOp3G48hWhxuUh9PsUqE5yxDwLsOVzCTqg9S5gxPQzF2eCN9J0I2XiIlLKvLQPIZ2Y_K7iYvVwjpNdgb4xhm9wuKoIVinYkF_6CwIzAawBWIDJAbix1IslkUPQMGbupTDtOgTiQ"
|
||||
|
||||
# This is the string the user-facing client (e.g. Roundcube) should send via IMAP to Dovecot.
|
||||
# We include the user and the above token separated by '\1' chars as per the XOAUTH2 spec.
|
||||
xoauth2 = base64.b64encode(f"user=user1@localhost.localdomain\1auth=Bearer {token}\1\1".encode("utf-8"))
|
||||
# If changing the user above, use the new output from the below line with the contents of the AUTHENTICATE command in test/test-files/auth/imap-oauth2-auth.txt
|
||||
print("XOAUTH2 string: " + str(xoauth2))
|
||||
|
||||
|
||||
class HTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
auth = self.headers.get("Authorization")
|
||||
if auth is None:
|
||||
self.send_response(401)
|
||||
self.end_headers()
|
||||
return
|
||||
if len(auth.split()) != 2:
|
||||
self.send_response(401)
|
||||
self.end_headers()
|
||||
return
|
||||
auth = auth.split()[1]
|
||||
# Valid session, respond with JSON containing the expected `email` claim to match as Dovecot username:
|
||||
if auth == token:
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({
|
||||
"email": "user1@localhost.localdomain",
|
||||
"email_verified": True,
|
||||
"sub": "82c1c334dcc6e311ae4aaebfe946c5e858f055aff1ce5a37aa7cc91aab17e35c"
|
||||
}).encode("utf-8"))
|
||||
else:
|
||||
self.send_response(401)
|
||||
self.end_headers()
|
||||
|
||||
server = HTTPServer(('', 80), HTTPRequestHandler)
|
||||
print("Starting server", flush=True)
|
||||
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
print("Received keyboard interrupt")
|
||||
finally:
|
||||
print("Exiting")
|
|
@ -0,0 +1,4 @@
|
|||
a0 NOOP See test/config/oauth2/provider.py to generate the below XOAUTH2 string
|
||||
a1 AUTHENTICATE XOAUTH2 dXNlcj11c2VyMUBsb2NhbGhvc3QubG9jYWxkb21haW4BYXV0aD1CZWFyZXIgZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBjM01pT2lKb2RIUndPaTh2Y0hKdmRtbGtaWEl1WlhoaGJYQnNaUzUwWlhOME9qZ3dNREF2SWl3aWMzVmlJam9pT0RKak1XTXpNelJrWTJNMlpUTXhNV0ZsTkdGaFpXSm1aVGswTm1NMVpUZzFPR1l3TlRWaFptWXhZMlUxWVRNM1lXRTNZMk01TVdGaFlqRTNaVE0xWXlJc0ltRjFaQ0k2SW0xaGFXeHpaWEoyWlhJaUxDSjFhV1FpT2lJNE9VNHpSME51TjFNMVkwOTBXa1pOUlRWQmVWaE5ibXhVUkZkVmNuRXpSbWQ0WVdseVdXaEZJbjAuenVDeXRBcmJwaGhKbjlYVF95OWNCZEdxRENObzY4dEJydE93UElzdUtOeUYzNDBTYU91WmEweGFyWm9meWd5dGREcEx0WXI1NlFsUFRLSW1pLW4xWldySGtSWmt3clFpNWpRLWpfbjJoRUFMMHZVVG9MYkRuWFlmYzVxMnc3ejdYMGFvQ21pSzgtZlY3S3g0Q1ZUTTdyaUJncEVsZjZGM3dOQUljWDZSMWlqVWg2SVNDTDBYWXNkb2dmOFdVTlppcFhZLU80UjdZSFhkT0VOdU9wM0c0OGhXaHh1VWg5UHNVcUU1eXhEd0xzT1Z6Q1RxZzlTNWd4UFF6RjJlQ045SjBJMlhpSWxMS3ZMUVBJWjJZX0s3aVl2VndqcE5kZ2I0eGhtOXd1S29JVmluWWtGXzZDd0l6QWF3QldJREpBYml4MUlzbGtVUFFNR2J1cFREdE9nVGlRAQE=
|
||||
a2 EXAMINE INBOX
|
||||
a3 LOGOUT
|
|
@ -21,6 +21,7 @@ function teardown() { _default_teardown ; }
|
|||
# dovecot (/usr/sbin/dovecot)
|
||||
# fetchmail (/usr/bin/fetchmail)
|
||||
# fail2ban-server (/usr/bin/python3 /usr/bin/fail2ban-server) - Started by fail2ban-wrapper.sh
|
||||
# mta-sts-daemon (/usr/bin/bin/python3 /usr/bin/mta-sts-daemon)
|
||||
# postgrey (postgrey) - NOTE: This process lacks path information to match with `--full` in pgrep / pkill
|
||||
# postsrsd (/usr/sbin/postsrsd) - NOTE: Also matches the wrapper: `/bin/bash /usr/local/bin/postsrsd-wrapper.sh`
|
||||
# saslauthd (/usr/sbin/saslauthd) - x5 of the same process are found running (1 is a parent of 4)
|
||||
|
@ -44,6 +45,7 @@ ENV_PROCESS_LIST=(
|
|||
dovecot
|
||||
fail2ban-server
|
||||
fetchmail
|
||||
mta-sts-daemon
|
||||
opendkim
|
||||
opendmarc
|
||||
postgrey
|
||||
|
@ -58,6 +60,7 @@ ENV_PROCESS_LIST=(
|
|||
--env ENABLE_CLAMAV=0
|
||||
--env ENABLE_FAIL2BAN=0
|
||||
--env ENABLE_FETCHMAIL=0
|
||||
--env ENABLE_MTA_STS=0
|
||||
--env ENABLE_OPENDKIM=0
|
||||
--env ENABLE_OPENDMARC=0
|
||||
--env ENABLE_POSTGREY=0
|
||||
|
@ -93,6 +96,7 @@ ENV_PROCESS_LIST=(
|
|||
--env ENABLE_AMAVIS=1
|
||||
--env ENABLE_FAIL2BAN=1
|
||||
--env ENABLE_FETCHMAIL=1
|
||||
--env ENABLE_MTA_STS=1
|
||||
--env ENABLE_OPENDKIM=1
|
||||
--env ENABLE_OPENDMARC=1
|
||||
--env FETCHMAIL_PARALLEL=1
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
load "${REPOSITORY_ROOT}/test/helper/setup"
|
||||
load "${REPOSITORY_ROOT}/test/helper/common"
|
||||
|
||||
BATS_TEST_NAME_PREFIX='[OAuth2] '
|
||||
CONTAINER1_NAME='dms-test_oauth2'
|
||||
CONTAINER2_NAME='dms-test_oauth2_provider'
|
||||
|
||||
function setup_file() {
|
||||
export DMS_TEST_NETWORK='test-network-oauth2'
|
||||
export DMS_DOMAIN='example.test'
|
||||
export FQDN_MAIL="mail.${DMS_DOMAIN}"
|
||||
export FQDN_OAUTH2="oauth2.${DMS_DOMAIN}"
|
||||
|
||||
# Link the test containers to separate network:
|
||||
# NOTE: If the network already exists, test will fail to start.
|
||||
docker network create "${DMS_TEST_NETWORK}"
|
||||
|
||||
# Setup local oauth2 provider service:
|
||||
docker run --rm -d --name "${CONTAINER2_NAME}" \
|
||||
--hostname "${FQDN_OAUTH2}" \
|
||||
--network "${DMS_TEST_NETWORK}" \
|
||||
--volume "${REPOSITORY_ROOT}/test/config/oauth2/:/app/" \
|
||||
docker.io/library/python:latest \
|
||||
python /app/provider.py
|
||||
|
||||
_run_until_success_or_timeout 20 sh -c "docker logs ${CONTAINER2_NAME} 2>&1 | grep 'Starting server'"
|
||||
|
||||
#
|
||||
# Setup DMS container
|
||||
#
|
||||
|
||||
# Add OAUTH2 configuration so that Dovecot can reach out to our mock provider (CONTAINER2)
|
||||
local ENV_OAUTH2_CONFIG=(
|
||||
--env ENABLE_OAUTH2=1
|
||||
--env OAUTH2_INTROSPECTION_URL=http://oauth2.example.test/userinfo/
|
||||
)
|
||||
|
||||
export CONTAINER_NAME=${CONTAINER1_NAME}
|
||||
local CUSTOM_SETUP_ARGUMENTS=(
|
||||
"${ENV_OAUTH2_CONFIG[@]}"
|
||||
|
||||
--hostname "${FQDN_MAIL}"
|
||||
--network "${DMS_TEST_NETWORK}"
|
||||
)
|
||||
|
||||
_init_with_defaults
|
||||
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||
_wait_for_tcp_port_in_container 143
|
||||
|
||||
# Set default implicit container fallback for helpers:
|
||||
export CONTAINER_NAME=${CONTAINER1_NAME}
|
||||
}
|
||||
|
||||
function teardown_file() {
|
||||
docker rm -f "${CONTAINER1_NAME}" "${CONTAINER2_NAME}"
|
||||
docker network rm "${DMS_TEST_NETWORK}"
|
||||
}
|
||||
|
||||
|
||||
@test "oauth2: imap connect and authentication works" {
|
||||
# An initial connection needs to be made first, otherwise the auth attempt fails
|
||||
_run_in_container_bash 'nc -vz 0.0.0.0 143'
|
||||
|
||||
_nc_wrapper 'auth/imap-oauth2-auth.txt' '-w 1 0.0.0.0 143'
|
||||
assert_output --partial 'Examine completed'
|
||||
}
|
Loading…
Reference in New Issue