Handle DKIM key generation and storage

master
Pierre Jaury 8 years ago
parent 2fa8b879db
commit 24680957f7

@ -20,7 +20,9 @@ default_config = {
'HOSTNAME': 'mail.freeposte.io',
'DOMAIN': 'freeposte.io',
'POSTMASTER': 'postmaster',
'DEBUG': False
'DEBUG': False,
'DKIM_PATH': '/dkim/{domain}.{selector}.key',
'DKIM_SELECTOR': 'dkim'
}
# Load configuration from the environment if available

@ -0,0 +1,21 @@
""" No crypto operation is done on keys.
They are thus represented as ASCII armored PEM.
"""
from OpenSSL import crypto
def gen_key(key_type=crypto.TYPE_RSA, bits=1024):
""" Generate and return a new RSA key.
"""
key = crypto.PKey()
key.generate_key(key_type, bits)
return crypto.dump_privatekey(crypto.FILETYPE_PEM, key)
def strip_key(pem):
""" Return only the b64 part of the ASCII armored PEM.
"""
key = crypto.load_privatekey(crypto.FILETYPE_PEM, pem)
public_pem = crypto.dump_publickey(crypto.FILETYPE_PEM, key)
return public_pem.replace(b"\n", b"").split(b"-----")[2]

@ -1,10 +1,14 @@
from freeposte.admin import db
from freeposte.admin import db, dkim
from freeposte import app
from sqlalchemy.ext import declarative
from passlib import context
from datetime import datetime
import re
import time
import os
import glob
# Many-to-many association table for domain managers
@ -34,6 +38,28 @@ class Domain(Base):
max_users = db.Column(db.Integer, nullable=False, default=0)
max_aliases = db.Column(db.Integer, nullable=False, default=0)
@property
def dkim_key(self):
file_path = app.config["DKIM_PATH"].format(
domain=self.name, selector=app.config["DKIM_SELECTOR"])
if os.path.exists(file_path):
with open(file_path, "rb") as handle:
return handle.read()
@dkim_key.setter
def dkim_key(self, value):
file_path = app.config["DKIM_PATH"].format(
domain=self.name, selector=app.config["DKIM_SELECTOR"])
with open(file_path, "wb") as handle:
handle.write(value)
@property
def dkim_publickey(self):
return dkim.strip_key(self.dkim_key).decode("utf8")
def generate_dkim_key(self):
self.dkim_key = dkim.gen_key()
def has_email(self, localpart):
for email in self.users + self.aliases:
if email.localpart == localpart:

@ -10,7 +10,7 @@ Domain details
{% block main_action %}
{% if current_user.global_admin %}
<a class="btn btn-primary" href="#">Regenerate keys</a>
<a class="btn btn-primary" href="{{ url_for(".domain_genkeys", domain_name=domain.name) }}">Regenerate keys</a>
{% endif %}
{% endblock %}
@ -26,8 +26,18 @@ Domain details
<td><pre>{{ domain.name }}. 600 IN MX 10 {{ config["HOSTNAME"] }}.</pre></td>
</tr>
<tr>
<th>DNS SPF entry</th>
<td><pre>{{ domain.name }}. 600 IN TXT "v=spf1 mx a:{{ config["HOSTNAME"] }} -all"</pre></td>
<th>DNS SPF entries</th>
<td><pre>
{{ domain.name }}. 600 IN TXT "v=spf1 mx a:{{ config["HOSTNAME"] }} -all"
{{ domain.name }}. 600 IN SPF "v=spf1 mx a:{{ config["HOSTNAME"] }} -all"</pre></td>
</tr>
<tr>
<th>DKIM public key</th>
<td><pre style="white-space: pre-wrap; word-wrap: break-word;">{{ domain.dkim_publickey }}</pre></td>
</tr>
<tr>
<th>DNS DKIM entry</th>
<td><pre style="white-space: pre-wrap; word-wrap: break-word;">{{ config["DKIM_SELECTOR"] }}._domainkey IN 600 TXT "v=DKIM1; k=rsa; p={{ domain.dkim_publickey }}"</pre></td>
</tr>
<tr>
<th>DNS DMARC entry</th>

@ -63,3 +63,11 @@ def domain_details(domain_name):
domain = utils.get_domain_admin(domain_name)
return flask.render_template('domain/details.html', domain=domain,
config=flask_app.config)
@app.route('/domain/genkeys/<domain_name>', methods=['GET'])
def domain_genkeys(domain_name):
domain = utils.get_domain_admin(domain_name)
domain.generate_dkim_key()
return flask.redirect(
flask.url_for(".domain_details", domain_name=domain_name))

@ -6,6 +6,7 @@ Flask-migrate
Flask-script
flask_wtf
WTForms-Components
PyOpenSSL
passlib
gunicorn
docker-py

@ -55,6 +55,7 @@ services:
env_file: freeposte.env
volumes:
- /freeposte/filter:/data
- /freeposte/dkim:/dkim
antispam:
build: rspamd
@ -79,6 +80,7 @@ services:
env_file: freeposte.env
volumes:
- /freeposte/freeposte:/data
- /freeposte/dkim:/dkim
- /var/run/docker.sock:/var/run/docker.sock:ro
webmail:

Loading…
Cancel
Save