Merge pull request #504 from modoboa/custom-tls-fix
Added custom tls cert support
This commit is contained in:
57
README.rst
57
README.rst
@@ -1,5 +1,5 @@
|
||||
modoboa-installer
|
||||
=================
|
||||
**modoboa-installer**
|
||||
=====================
|
||||
|
||||
|workflow| |codecov|
|
||||
|
||||
@@ -76,7 +76,7 @@ If you want more information about the installation process, add the
|
||||
``--debug`` option to your command line.
|
||||
|
||||
Upgrade mode
|
||||
------------
|
||||
============
|
||||
|
||||
An experimental upgrade mode is available.
|
||||
|
||||
@@ -92,7 +92,7 @@ You can activate it as follows::
|
||||
It will automatically install latest versions of modoboa and its plugins.
|
||||
|
||||
Backup mode
|
||||
-----------
|
||||
===========
|
||||
|
||||
An experimental backup mode is available.
|
||||
|
||||
@@ -129,7 +129,7 @@ configuration file (set enabled to False).
|
||||
This can be useful for larger instance.
|
||||
|
||||
Restore mode
|
||||
------------
|
||||
============
|
||||
|
||||
An experimental restore mode is available.
|
||||
|
||||
@@ -140,7 +140,7 @@ You can start the process as follows::
|
||||
Then wait for the process to finish.
|
||||
|
||||
Change the generated hostname
|
||||
-----------------------------
|
||||
=============================
|
||||
|
||||
By default, the installer will setup your email server using the
|
||||
following hostname: ``mail.<your domain>``. If you want a different
|
||||
@@ -159,14 +159,26 @@ modifications.
|
||||
Finally, run the installer without the
|
||||
``--stop-after-configfile-check`` option.
|
||||
|
||||
Let's Encrypt certificate
|
||||
-------------------------
|
||||
Certificate
|
||||
===========
|
||||
|
||||
Self-signed
|
||||
-----------
|
||||
|
||||
It is the default type of certificate the installer will generate, it
|
||||
is however not recommended for production use.
|
||||
|
||||
Letsencrypt
|
||||
-----------
|
||||
|
||||
.. warning::
|
||||
|
||||
Please note this option requires the hostname you're using to be
|
||||
valid (ie. it can be resolved with a DNS query) and to match the
|
||||
server you're installing Modoboa on.
|
||||
Please note that by using this option, you agree to the `ToS
|
||||
<https://community.letsencrypt.org/tos>`_ of
|
||||
letsencrypt and that your IP will be logged (see ToS).
|
||||
Please also note this option requires the hostname you're using to be
|
||||
valid (ie. it can be resolved with a DNS query) and to match the
|
||||
server you're installing Modoboa on.
|
||||
|
||||
If you want to generate a valid certificate using `Let's Encrypt
|
||||
<https://letsencrypt.org/>`_, edit the ``installer.cfg`` file and
|
||||
@@ -175,6 +187,8 @@ modify the following settings::
|
||||
[certificate]
|
||||
generate = true
|
||||
type = letsencrypt
|
||||
tls_cert_file_path =
|
||||
tls_key_file_path =
|
||||
|
||||
[letsencrypt]
|
||||
email = admin@example.com
|
||||
@@ -182,6 +196,27 @@ modify the following settings::
|
||||
Change the ``email`` setting to a valid value since it will be used
|
||||
for account recovery.
|
||||
|
||||
Manual
|
||||
------
|
||||
|
||||
.. warning::
|
||||
|
||||
It is not possible to configure manual certs interactively, so
|
||||
you'll have to do it in 2 steps. Please run ``run.py`` with
|
||||
`--stop-after-configfile-check` first, configure your file as
|
||||
desired and apply the configuration as written bellow. Then run
|
||||
``run.py`` again but without `--stop-after-configfile-check` or
|
||||
`--interactive`.
|
||||
|
||||
If you want to use already generated certs, simply edit the
|
||||
``installer.cfg`` file and modify the following settings::
|
||||
|
||||
[certificate]
|
||||
generate = true
|
||||
type = manual
|
||||
tls_cert_file_path = *path to tls key file*
|
||||
tls_key_file_path = * path to tls fullchain file*
|
||||
|
||||
.. |workflow| image:: https://github.com/modoboa/modoboa-installer/workflows/Modoboa%20installer/badge.svg
|
||||
.. |codecov| image:: http://codecov.io/github/modoboa/modoboa-installer/coverage.svg?branch=master
|
||||
:target: http://codecov.io/github/modoboa/modoboa-installer?branch=master
|
||||
|
||||
@@ -39,7 +39,16 @@ ConfigDictTemplate = [
|
||||
"default": "self-signed",
|
||||
"customizable": True,
|
||||
"question": "Please choose your certificate type",
|
||||
"values": ["self-signed", "letsencrypt"],
|
||||
"values": ["self-signed", "letsencrypt", "manual"],
|
||||
"non_interactive_values": ["manual"],
|
||||
},
|
||||
{
|
||||
"option": "tls_cert_file_path",
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"option": "tls_key_file_path",
|
||||
"default": ""
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ from . import package
|
||||
from . import utils
|
||||
|
||||
|
||||
class CertificateBackend(object):
|
||||
class CertificateBackend:
|
||||
"""Base class."""
|
||||
|
||||
def __init__(self, config):
|
||||
@@ -24,13 +24,44 @@ class CertificateBackend(object):
|
||||
return False
|
||||
return True
|
||||
|
||||
def generate_cert(self):
|
||||
"""Create a certificate."""
|
||||
pass
|
||||
|
||||
|
||||
class ManualCertificate(CertificateBackend):
|
||||
"""Use certificate provided."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
path_correct = True
|
||||
self.tls_cert_file_path = self.config.get("certificate",
|
||||
"tls_key_file_path")
|
||||
self.tls_key_file_path = self.config.get("certificate",
|
||||
"tls_cert_file_path")
|
||||
|
||||
if not os.path.exists(self.tls_key_file_path):
|
||||
utils.error("'tls_key_file_path' path is not accessible")
|
||||
path_correct = False
|
||||
if not os.path.exists(self.tls_cert_file_path):
|
||||
utils.error("'tls_cert_file_path' path is not accessible")
|
||||
path_correct = False
|
||||
|
||||
if not path_correct:
|
||||
sys.exit(1)
|
||||
|
||||
self.config.set("general", "tls_key_file",
|
||||
self.tls_key_file_path)
|
||||
self.config.set("general", "tls_cert_file",
|
||||
self.tls_cert_file_path)
|
||||
|
||||
|
||||
class SelfSignedCertificate(CertificateBackend):
|
||||
"""Create a self signed certificate."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Sanity checks."""
|
||||
super(SelfSignedCertificate, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.config.has_option("general", "tls_key_file"):
|
||||
# Compatibility
|
||||
return
|
||||
@@ -65,7 +96,7 @@ class LetsEncryptCertificate(CertificateBackend):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Update config."""
|
||||
super(LetsEncryptCertificate, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.hostname = self.config.get("general", "hostname")
|
||||
self.config.set("general", "tls_cert_file", (
|
||||
"/etc/letsencrypt/live/{}/fullchain.pem".format(self.hostname)))
|
||||
@@ -119,8 +150,13 @@ class LetsEncryptCertificate(CertificateBackend):
|
||||
|
||||
def get_backend(config):
|
||||
"""Return the appropriate backend."""
|
||||
if not config.getboolean("certificate", "generate"):
|
||||
cert_type = config.get("certificate", "type")
|
||||
condition = (not config.getboolean("certificate", "generate") and
|
||||
cert_type != "manual")
|
||||
if condition:
|
||||
return None
|
||||
if config.get("certificate", "type") == "letsencrypt":
|
||||
if cert_type == "letsencrypt":
|
||||
return LetsEncryptCertificate(config)
|
||||
if cert_type == "manual":
|
||||
return ManualCertificate(config)
|
||||
return SelfSignedCertificate(config)
|
||||
|
||||
@@ -316,6 +316,17 @@ def get_entry_value(entry, interactive):
|
||||
|
||||
if entry.get("values") and user_value != "":
|
||||
user_value = values[int(user_value)]
|
||||
|
||||
non_interactive_values = entry.get("non_interactive_values", [])
|
||||
if user_value in non_interactive_values:
|
||||
error(
|
||||
f"{user_value} cannot be set interactively. "
|
||||
"Please configure installer.cfg manually by running "
|
||||
"'python3 run.py --stop-after-configfile-check domain'. "
|
||||
"Check modoboa-installer README for more information."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
return user_value if user_value else default_value
|
||||
|
||||
|
||||
|
||||
2
run.py
2
run.py
@@ -203,7 +203,7 @@ def main(input_args):
|
||||
if not args.skip_checks:
|
||||
utils.printcolor("Checking the installer...", utils.BLUE)
|
||||
checks.handle()
|
||||
utils.success("Checks complete")
|
||||
utils.success("Checks complete\n")
|
||||
|
||||
is_config_file_available, outdate_config = utils.check_config_file(
|
||||
args.configfile, args.interactive, args.upgrade, args.backup, is_restoring)
|
||||
|
||||
Reference in New Issue
Block a user