Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added setup instructions for Dovecot oauth2 support #563

Merged
merged 5 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion modoboa_installer/config_dict_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ def is_email(user_input):
"option": "extensions",
"default": (
"modoboa-amavis "
"modoboa-postfix-autoreply modoboa-sievefilters "
"modoboa-webmail modoboa-contacts "
"modoboa-radicale"
),
Expand Down
40 changes: 34 additions & 6 deletions modoboa_installer/scripts/dovecot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import pwd
import shutil
import uuid

from .. import database
from .. import package
Expand All @@ -14,7 +15,6 @@


class Dovecot(base.Installer):

"""Dovecot installer."""

appname = "dovecot"
Expand All @@ -27,7 +27,9 @@ class Dovecot(base.Installer):
}
config_files = [
"dovecot.conf", "dovecot-dict-sql.conf.ext", "conf.d/10-ssl.conf",
"conf.d/10-master.conf", "conf.d/20-lmtp.conf", "conf.d/10-ssl-keys.try"]
"conf.d/10-master.conf", "conf.d/20-lmtp.conf", "conf.d/10-ssl-keys.try",
"conf.d/dovecot-oauth2.conf.ext"
]
with_user = True

def setup_user(self):
Expand All @@ -53,17 +55,35 @@ def get_packages(self):
if package.backend.FORMAT == "deb":
if "pop3" in self.config.get("dovecot", "extra_protocols"):
packages += ["dovecot-pop3d"]
return super(Dovecot, self).get_packages() + packages
return super().get_packages() + packages

def install_packages(self):
"""Preconfigure Dovecot if needed."""
package.backend.preconfigure(
"dovecot-core", "create-ssl-cert", "boolean", "false")
super(Dovecot, self).install_packages()
super().install_packages()

def create_oauth2_app(self):
"""Create a application for Oauth2 authentication."""
# FIXME: how can we check that application already exists ?
venv_path = self.config.get("modoboa", "venv_path")
python_path = os.path.join(venv_path, "bin", "python")
instance_path = self.config.get("modoboa", "instance_path")
script_path = os.path.join(instance_path, "manage.py")
client_id = "dovecot"
client_secret = str(uuid.uuid4())
cmd = (
f"{python_path} {script_path} createapplication "
f"--name=Dovecot --skip-authorization "
f"--client-id={client_id} --client-secret={client_secret} "
f"confidential client-credentials"
)
utils.exec_cmd(cmd)
return client_id, client_secret

def get_template_context(self):
"""Additional variables."""
context = super(Dovecot, self).get_template_context()
context = super().get_template_context()
pw_mailbox = pwd.getpwnam(self.mailboxes_owner)
dovecot_package = {"deb": "dovecot-core", "rpm": "dovecot"}
ssl_protocol_parameter = "ssl_protocols"
Expand All @@ -84,6 +104,13 @@ def get_template_context(self):
# Protocols are automatically guessed on debian/ubuntu
protocols = ""

oauth2_client_id, oauth2_client_secret = self.create_oauth2_app()
hostname = self.config.get("general", "hostname")
oauth2_introspection_url = (
f"https://{oauth2_client_id}:{oauth2_client_secret}"
f"@{hostname}/api/o/introspect/"
)

context.update({
"db_driver": self.db_driver,
"mailboxes_owner_uid": pw_mailbox[2],
Expand All @@ -100,7 +127,8 @@ def get_template_context(self):
"radicale_auth_socket_path": os.path.basename(
self.config.get("dovecot", "radicale_auth_socket_path")),
"modoboa_2_2_or_greater": "" if self.modoboa_2_2_or_greater else "#",
"not_modoboa_2_2_or_greater": "" if not self.modoboa_2_2_or_greater else "#"
"not_modoboa_2_2_or_greater": "" if not self.modoboa_2_2_or_greater else "#",
"oauth2_introspection_url": oauth2_introspection_url
})
return context

Expand Down
3 changes: 2 additions & 1 deletion modoboa_installer/scripts/files/dovecot/conf.d/10-auth.conf
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ auth_master_user_separator = *
# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey
# gss-spnego
# NOTE: See also disable_plaintext_auth setting.
auth_mechanisms = plain login
auth_mechanisms = plain login oauthbearer xoauth2

##
## Password and user databases
Expand All @@ -120,6 +120,7 @@ auth_mechanisms = plain login

#!include auth-system.conf.ext
!include auth-sql.conf.ext
!include auth-oauth2.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
passdb {
driver = oauth2
mechanisms = xoauth2 oauthbearer
args = /etc/dovecot/conf.d/dovecot-oauth2.conf.ext
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
introspection_mode = post
introspection_url = %{oauth2_introspection_url}
username_attribute = username
tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt
active_attribute = active
active_value = true
1 change: 1 addition & 0 deletions modoboa_installer/scripts/files/uwsgi/modoboa.ini.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ socket = %uwsgi_socket_path
chmod-socket = 660
vacuum = true
single-interpreter = True
buffer-size = 8192