101 lines
5.6 KiB
Markdown
101 lines
5.6 KiB
Markdown
# Rspamd DKIM integration (0.0.2)
|
|
|
|
PostfixAdmin-RS can manage file-based DKIM signing for Rspamd without growing a large `domain { ... }` block.
|
|
It uses Rspamd's supported `selector_map` and `path_map` mechanism. DKIM is always per-domain: every domain maps to its own selector and private-key path. `default_selector` is only the default selector name used for new mappings; it is not a shared key.
|
|
|
|
## Managed layout
|
|
|
|
New keys are stored as:
|
|
|
|
```text
|
|
/var/lib/rspamd/dkim/<domain>/<selector>.private
|
|
/var/lib/rspamd/dkim/<domain>/<selector>.txt
|
|
```
|
|
|
|
The `.txt` sidecar contains the DNS TXT record returned by `rspamadm dkim_keygen`.
|
|
The application maintains:
|
|
|
|
```text
|
|
/var/lib/rspamd/dkim/postfixadmin-rs-selectors.map
|
|
/var/lib/rspamd/dkim/postfixadmin-rs-paths.map
|
|
```
|
|
|
|
and a small marked block in `/etc/rspamd/local.d/dkim_signing.conf`:
|
|
|
|
```ucl
|
|
# BEGIN PostfixAdmin-RS managed DKIM maps
|
|
selector_map = "/var/lib/rspamd/dkim/postfixadmin-rs-selectors.map";
|
|
path_map = "/var/lib/rspamd/dkim/postfixadmin-rs-paths.map";
|
|
# END PostfixAdmin-RS managed DKIM maps
|
|
```
|
|
|
|
Existing settings such as `auth_only`, `sign_local`, `use_domain`, and `try_fallback` are left untouched.
|
|
If `selector_map` or `path_map` already exists outside the managed block, PostfixAdmin-RS refuses to edit the file instead of creating ambiguous Rspamd configuration.
|
|
|
|
## Security model
|
|
|
|
Do not run the web service as root. The service account needs write access only to the DKIM key directory, the two map files, and (if automatic bootstrap is desired) `dkim_signing.conf`.
|
|
Rspamd needs read access to private keys.
|
|
|
|
In 0.0.2 the packaged permission helper creates a dedicated `postfixadmin-rspamd` group shared only by the `postfixadmin` service account and the detected Rspamd runtime user. The DKIM directory is setgid so generated keys inherit that group. Keep private keys at mode `0640`.
|
|
|
|
Reload is deliberately an argv-only configured command. If automatic reload is wanted, use a tightly scoped sudoers rule that permits only `systemctl reload rspamd`, then configure:
|
|
|
|
```toml
|
|
[rspamd_dkim]
|
|
reload_command = ["/usr/bin/sudo", "-n", "/usr/bin/systemctl", "reload", "rspamd"]
|
|
```
|
|
|
|
PostfixAdmin-RS never invokes `sh -c` for this integration.
|
|
|
|
## Existing keys
|
|
|
|
Use **Podepnij klucz** in the DKIM page. The file must already exist below `rspamd_dkim.key_dir`; arbitrary files outside that tree cannot be adopted or deleted.
|
|
This is useful for existing layouts such as:
|
|
|
|
```text
|
|
/var/lib/rspamd/dkim/example.org/default.private
|
|
```
|
|
|
|
Set the selector to the selector already published in DNS (for example `mail`). The filename does not need to match the selector when adopting an existing key.
|
|
|
|
## Generation flow
|
|
|
|
1. Validate domain/selector and admin scope.
|
|
2. Generate an RSA key with `rspamadm dkim_keygen`.
|
|
3. Store private key with restrictive permissions and save the DNS record sidecar.
|
|
4. Atomically update selector/path maps.
|
|
5. Run `rspamadm configtest`.
|
|
6. Reload Rspamd if a reload command is configured.
|
|
|
|
If configuration testing fails while bootstrapping the managed block, the previous `dkim_signing.conf` is restored.
|
|
|
|
## Import obecnego `domain { ... }`
|
|
|
|
Global-admin moze uzyc **Importuj istniejące domain{}**. Parser bierze proste domenowe bloki z obecnego `dkim_signing.conf`, odczytuje `path` i `selector`, odrzuca sciezki spoza `rspamd_dkim.key_dir`, a nastepnie przenosi poprawne wpisy do map.
|
|
|
|
Przed migracja powstaje kopia `<key_dir>/dkim_signing.conf.pre-postfixadmin-rs`. Tylko poprawnie zaimportowane bloki domenowe sa usuwane z aktywnej konfiguracji. Jezeli zapis lub `rspamadm configtest` nie przejdzie, aplikacja przywraca poprzednia konfiguracje i mapy. To jest istotne, bo istniejace per-domain `path`/`selector` moga miec pierwszenstwo przed wartosciami z map.
|
|
|
|
Rspamd obserwuje lokalne pliki map i odswieza je po zmianach, wiec po jednorazowym zaladowaniu konfiguracji `selector_map/path_map` kolejne zmiany map nie wymagaja przebudowy wielkiego bloku `domain { ... }`. Opcjonalny reload pozostaje dostepny, gdy chcesz wymusic natychmiastowe przeladowanie procesu.
|
|
|
|
## Mailbox-user read-only view
|
|
|
|
When `[dkim].user_read_only = true`, a mailbox user can open DKIM and see the complete public DNS record for their own domain. The API may return records from both the PostfixAdmin DKIM tables and Rspamd, but it never exposes private-key bytes or private-key paths to mailbox users.
|
|
|
|
In SSH development mode the application cannot directly read `/var/lib/rspamd/dkim` on the remote mail server. `dev.sh` therefore creates a temporary public-only cache under `.dev/rspamd-remote-public`: it reads the remote maps/config and derives the public key with OpenSSL on the remote host. Only the final public TXT record is copied back; private key bytes never leave the mail server. Disable this development helper with `POSTFIXADMIN_RS_DEV_RSPAMD_PUBLIC_SYNC=false`.
|
|
|
|
## Host permissions for 0.0.2
|
|
|
|
`postfixadmin-rs` never needs to run as root. For the standard paths, install the package and run once:
|
|
|
|
```bash
|
|
sudo /usr/lib/postfixadmin-rs/setup-rspamd-dkim-permissions
|
|
sudo systemctl restart postfixadmin-rs rspamd
|
|
```
|
|
|
|
The helper creates a dedicated `postfixadmin-rspamd` group, adds the PostfixAdmin-RS and Rspamd runtime users to it, prepares `/var/lib/rspamd/dkim` as a setgid shared directory, keeps private keys at `0640`, and grants the service write access only to `dkim_signing.conf` rather than all of `/etc/rspamd/local.d`.
|
|
|
|
You can override detection with `POSTFIXADMIN_RS_RSPAMD_USER`, `POSTFIXADMIN_RS_RSPAMD_KEY_DIR`, and `POSTFIXADMIN_RS_RSPAMD_SIGNING_CONFIG` when the host uses non-standard names or paths.
|
|
|
|
Filesystem failures now include the operation and exact path in the API error instead of the generic `I/O operation failed` message.
|