2017: rspamd: get dkim keys via REST API instead of filesystem r=mergify[bot] a=ghostwheel42

## What type of PR?

enhancement

## What does this PR do?

rspamd now uses hashicorp's vault api v1 to get dkim keys and selectors for a domain.
this allows future enhancement (multiple keys) without reconfiguring and restarting rspamd.
it also makes mounting the /dkim volume into the rspamd container unnecessary.

### Related issue(s)

- improves and closes #2012 
- allows to implement key rotation using multiple selectors (see #1700)
- allows to implement dkim for alternate domains (see #1519)
- fixes and closes #1345 (selector transmitted by admin container is used)
- closes #1179 (no keys on disk)
- allows to implement key rotation from the outside (ie. via a helper script talking to some dns provider's api) (see #547)

## Prerequisites

- [X] In case of feature or enhancement: documentation updated accordingly
- [X] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/workflow.html#changelog) entry file.


Co-authored-by: Alexander Graf <ghostwheel42@users.noreply.github.com>
master
bors[bot] 3 years ago committed by GitHub
commit a5b1d36171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,3 +1,3 @@
__all__ = [ __all__ = [
'auth', 'postfix', 'dovecot', 'fetch' 'auth', 'postfix', 'dovecot', 'fetch', 'rspamd'
] ]

@ -0,0 +1,30 @@
from mailu import models
from mailu.internal import internal
import flask
def vault_error(*messages, status=404):
return flask.make_response(flask.jsonify({'errors':messages}), status)
# rspamd key format:
# {"selectors":[{"pubkey":"...","domain":"...","valid_start":TS,"valid_end":TS,"key":"...","selector":"...","bits":...,"alg":"..."}]}
# hashicorp vault answer format:
# {"request_id":"...","lease_id":"","renewable":false,"lease_duration":2764800,"data":{...see above...},"wrap_info":null,"warnings":null,"auth":null}
@internal.route("/rspamd/vault/v1/dkim/<domain_name>", methods=['GET'])
def rspamd_dkim_key(domain_name):
domain = models.Domain.query.get(domain_name) or flask.abort(vault_error('unknown domain'))
key = domain.dkim_key or flask.abort(vault_error('no dkim key', status=400))
return flask.jsonify({
'data': {
'selectors': [
{
'domain' : domain.name,
'key' : key.decode('utf8'),
'selector': flask.current_app.config.get('DKIM_SELECTOR', 'dkim'),
}
]
}
})

@ -1,4 +1,6 @@
try_fallback = true; try_fallback = false;
path = "/dkim/$domain.$selector.key";
selector = "dkim"
use_esld = false; use_esld = false;
allow_username_mismatch = true;
use_vault = true;
vault_url = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/vault";
vault_token = "mailu";

@ -1,4 +1,6 @@
try_fallback = true; try_fallback = false;
path = "/dkim/$domain.$selector.key";
use_esld = false; use_esld = false;
allow_username_mismatch = true; allow_username_mismatch = true;
use_vault = true;
vault_url = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/vault";
vault_token = "mailu";

@ -11,6 +11,7 @@ log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING"))
# Actual startup script # Actual startup script
os.environ["REDIS_ADDRESS"] = system.get_host_address_from_environment("REDIS", "redis") os.environ["REDIS_ADDRESS"] = system.get_host_address_from_environment("REDIS", "redis")
os.environ["ADMIN_ADDRESS"] = system.get_host_address_from_environment("ADMIN", "admin")
if os.environ.get("ANTIVIRUS") == 'clamav': if os.environ.get("ANTIVIRUS") == 'clamav':
os.environ["ANTIVIRUS_ADDRESS"] = system.get_host_address_from_environment("ANTIVIRUS", "antivirus:3310") os.environ["ANTIVIRUS_ADDRESS"] = system.get_host_address_from_environment("ANTIVIRUS", "antivirus:3310")

@ -0,0 +1 @@
rspamd: get dkim keys via REST API instead of filesystem
Loading…
Cancel
Save