docker-mailserver/target/scripts/check-for-changes.sh

218 lines
7.9 KiB
Bash
Raw Permalink Normal View History

#!/bin/bash
fix: `check-for-changes.sh` should not fall out of sync with shared logic (#2260) Removes duplicate logic from `check-for-changes.sh` that is used/maintained elsewhere to avoid risk of problems, as this code is already starting to diverge / rot. --- Previously the change detection support has had code added for rebuilding config upon change detection which is the same as code run during startup scripts. Unfortunately over time this has fallen out of sync. Mostly the startup scripts would get maintenance and the contributor and reviewers may not have been aware of the duplicate code handled by `check-for-changes.sh`. That code was starting to diverge in addition to some changes in structure (_eg: relay host logic seems interleaved here vs separated out in startup scripts_). I wanted to address this before it risks becoming a much bigger headache. Rather than bloat `helper-functions.sh` further, I've added a `helpers/` folder extracting relevant common logic between startup scripts and `changedetector`. If you want to follow that process I've kept scoped commits to make those diffs easier. Some minor changes/improvements were added but nothing significant. --- - chore: Extract relay host logic to new `relay.sh` helper - chore: Extract `/etc/postfix/sasl_passwd` logic to new `sasl.sh` helper - chore: Extract `postfix-accounts.cf` logic to new `accounts.sh` helper - chore: Extract `/etc/aliases` logic to new `aliases.sh` helper - chore: Extract `/etc/postfix/vhost` logic to new `postfix.sh` helper - chore: Add inline docs for Postfix configs > These are possibly more verbose than needed and can be reduced at a later stage. > They are helpful during this refactor process while investigating that everything is handled correctly. `accounts.sh`: - Add note regarding potential bug for bare domain setups with `/etc/postfix/vhost` and `mydestination` sharing same domain value. `relay.sh`: - Remove the tabs for a single space delimiter, revised associated comment. - Add PR reference for original `_populate_relayhost_map` implementation which has some useful details. Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Co-authored-by: Casper <casperklein@users.noreply.github.com>
2021-11-20 21:33:49 +01:00
# TODO: Adapt for compatibility with LDAP
# Only the cert renewal change detection may be relevant for LDAP?
refactor: letsencrypt implicit location discovery (#2525) * chore: Extract letsencrypt logic into methods This allows other scripts to share the functionality to discover the correct letsencrypt folder from the 3 possible locations (where specific order is important). As these methods should now return a string value, the `return 1` after a panic is now dropped. * chore: Update comments The todo is resolved with this PR, `_setup_ssl` will be called by both cert conditional statements with purpose for each better documented to maintainers at the start of the logic block. * refactor: Defer most logic to helper/ssl.sh The loop is no longer required, extraction is delegated to `_setup_ssl` now. For the change event prevention, we retrieve the relevant FQDN via the new helper method, beyond that it's just indentation diff. `check-for-changes.sh` adjusted to allow locally scoped var declarations by wrapping a function. Presently no loop control flow is needed so this seems fine. Made it clear that `CHANGED` is local and `CHKSUM_FILE` is not. Panic scope doesn't require `SSL_TYPE` for context, it's clearly`letsencrypt`. * fix: Correctly match wildcard results Now that the service configs are properly updated, when the services restart they will return a cert with the SAN `DNS:*.example.test`, which is valid for `mail.example.test`, however the test function did not properly account for this in the regexp query. Resolved by truncating the left-most DNS label from FQDN and adding a third check to match a returned wildcard DNS result. Extracted out the common logic to create the regexp query and renamed the methods to communicate more clearly that they check the FQDN is supported, not necessarily explicitly listed by the cert. * tests(letsencrypt): Enable remaining tests These will now pass. Adjusted comments accordingly. Added an additional test on a fake FQDN that should still be valid to a wildcard cert (SNI validation in a proper setup would reject the connection afterwards). Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
2022-04-18 12:52:50 +02:00
# CHKSUM_FILE global is imported from this file:
# shellcheck source=./helpers/index.sh
source /usr/local/bin/helpers/index.sh
refactor: letsencrypt implicit location discovery (#2525) * chore: Extract letsencrypt logic into methods This allows other scripts to share the functionality to discover the correct letsencrypt folder from the 3 possible locations (where specific order is important). As these methods should now return a string value, the `return 1` after a panic is now dropped. * chore: Update comments The todo is resolved with this PR, `_setup_ssl` will be called by both cert conditional statements with purpose for each better documented to maintainers at the start of the logic block. * refactor: Defer most logic to helper/ssl.sh The loop is no longer required, extraction is delegated to `_setup_ssl` now. For the change event prevention, we retrieve the relevant FQDN via the new helper method, beyond that it's just indentation diff. `check-for-changes.sh` adjusted to allow locally scoped var declarations by wrapping a function. Presently no loop control flow is needed so this seems fine. Made it clear that `CHANGED` is local and `CHKSUM_FILE` is not. Panic scope doesn't require `SSL_TYPE` for context, it's clearly`letsencrypt`. * fix: Correctly match wildcard results Now that the service configs are properly updated, when the services restart they will return a cert with the SAN `DNS:*.example.test`, which is valid for `mail.example.test`, however the test function did not properly account for this in the regexp query. Resolved by truncating the left-most DNS label from FQDN and adding a third check to match a returned wildcard DNS result. Extracted out the common logic to create the regexp query and renamed the methods to communicate more clearly that they check the FQDN is supported, not necessarily explicitly listed by the cert. * tests(letsencrypt): Enable remaining tests These will now pass. Adjusted comments accordingly. Added an additional test on a fake FQDN that should still be valid to a wildcard cert (SNI validation in a proper setup would reject the connection afterwards). Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
2022-04-18 12:52:50 +02:00
_log 'debug' 'Starting changedetector'
# ATTENTION: Do not remove!
# This script requires some environment variables to be properly set.
# POSTMASTER_ADDRESS (for helpers/alias.sh) is read from /etc/dms-settings
# shellcheck source=/dev/null
source /etc/dms-settings
# HOSTNAME and DOMAINNAME are used by helpers/ssl.sh and _monitored_files_checksums
# These are not stored in /etc/dms-settings
# TODO: It is planned to stop overriding HOSTNAME and replace that
# usage with DMS_HOSTNAME, which should remove the need to call this:
_obtain_hostname_and_domainname
# This is a helper to properly set all Rspamd-related environment variables
# correctly and in one place.
_rspamd_get_envs
Final Migration Step (#6) * first migration steps * altered issue templates * altered README * removed .travis.yml * adjusting registry & repository, Dockerfile and compose.env * Close stale issues automatically * Integrated CI with Github Actions (#3) * feat: integrated ci with github actions * fix: use secrets for docker org and update image * docs: clarify why we use -t if no tty exists * fix: correct remaining references to old repo chore: prettier automatically updated markdown as well * fix: hardcode docker org * change testing image to just testing * ci: add armv7 as a supported platform * finished migration steps * corrected linting in build-push action * corrected linting in build-push action (2) * minor preps for PR * correcting push on pull request and minor details * adjusted workflows to adhere closer to @wernerfred's diagram * minor patches * adjusting Dockerfile's installation of base packages * adjusting schedule for stale issue action * reverting license text * improving CONTRIBUTING.md PR text * Update CONTRIBUTING.md * a bigger patch at the end * moved all scripts into one directory under target/scripts/ * moved the quota-warning.sh script into target/scripts/ and removed empty directory /target/dovecot/scripts * minor fixes here and there * adjusted workflows for use a fully qualified name (i.e. docker.io/...) * improved on the Dockerfile layer count * corrected local tests - now they (actually) work (fine)! * corrected start-mailserver.sh to make use of defaults consistently * removed very old, deprecated variables (actually only one) * various smaller improvements in the end * last commit before merging #6 * rearranging variables to use alphabetic order Co-authored-by: casperklein <casperklein@users.noreply.github.com> Co-authored-by: Nick Pappas <radicand@users.noreply.github.com> Co-authored-by: William Desportes <williamdes@wdes.fr>
2021-01-16 10:16:05 +01:00
# verify checksum file exists; must be prepared by start-mailserver.sh
2023-05-24 09:06:59 +02:00
if [[ ! -f ${CHKSUM_FILE} ]]; then
_exit_with_error "'${CHKSUM_FILE}' is missing" 0
fi
_log 'trace' "Using postmaster address '${POSTMASTER_ADDRESS}'"
_log 'debug' "Changedetector is ready"
2023-05-26 01:01:41 +02:00
function _check_for_changes() {
# get chksum and check it, no need to lock config yet
_monitored_files_checksums >"${CHKSUM_FILE}.new"
cmp --silent -- "${CHKSUM_FILE}" "${CHKSUM_FILE}.new"
# cmp return codes
# 0 files are identical
# 1 files differ
# 2 inaccessible or missing argument
2023-05-24 09:06:59 +02:00
if [[ ${?} -eq 1 ]]; then
_log 'info' 'Change detected'
_create_lock # Shared config safety lock
refactor: letsencrypt implicit location discovery (#2525) * chore: Extract letsencrypt logic into methods This allows other scripts to share the functionality to discover the correct letsencrypt folder from the 3 possible locations (where specific order is important). As these methods should now return a string value, the `return 1` after a panic is now dropped. * chore: Update comments The todo is resolved with this PR, `_setup_ssl` will be called by both cert conditional statements with purpose for each better documented to maintainers at the start of the logic block. * refactor: Defer most logic to helper/ssl.sh The loop is no longer required, extraction is delegated to `_setup_ssl` now. For the change event prevention, we retrieve the relevant FQDN via the new helper method, beyond that it's just indentation diff. `check-for-changes.sh` adjusted to allow locally scoped var declarations by wrapping a function. Presently no loop control flow is needed so this seems fine. Made it clear that `CHANGED` is local and `CHKSUM_FILE` is not. Panic scope doesn't require `SSL_TYPE` for context, it's clearly`letsencrypt`. * fix: Correctly match wildcard results Now that the service configs are properly updated, when the services restart they will return a cert with the SAN `DNS:*.example.test`, which is valid for `mail.example.test`, however the test function did not properly account for this in the regexp query. Resolved by truncating the left-most DNS label from FQDN and adding a third check to match a returned wildcard DNS result. Extracted out the common logic to create the regexp query and renamed the methods to communicate more clearly that they check the FQDN is supported, not necessarily explicitly listed by the cert. * tests(letsencrypt): Enable remaining tests These will now pass. Adjusted comments accordingly. Added an additional test on a fake FQDN that should still be valid to a wildcard cert (SNI validation in a proper setup would reject the connection afterwards). Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
2022-04-18 12:52:50 +02:00
local CHANGED
CHANGED=$(_get_changed_files "${CHKSUM_FILE}" "${CHKSUM_FILE}.new")
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
_handle_changes
_remove_lock
_log 'debug' 'Completed handling of detected change'
refactor: letsencrypt implicit location discovery (#2525) * chore: Extract letsencrypt logic into methods This allows other scripts to share the functionality to discover the correct letsencrypt folder from the 3 possible locations (where specific order is important). As these methods should now return a string value, the `return 1` after a panic is now dropped. * chore: Update comments The todo is resolved with this PR, `_setup_ssl` will be called by both cert conditional statements with purpose for each better documented to maintainers at the start of the logic block. * refactor: Defer most logic to helper/ssl.sh The loop is no longer required, extraction is delegated to `_setup_ssl` now. For the change event prevention, we retrieve the relevant FQDN via the new helper method, beyond that it's just indentation diff. `check-for-changes.sh` adjusted to allow locally scoped var declarations by wrapping a function. Presently no loop control flow is needed so this seems fine. Made it clear that `CHANGED` is local and `CHKSUM_FILE` is not. Panic scope doesn't require `SSL_TYPE` for context, it's clearly`letsencrypt`. * fix: Correctly match wildcard results Now that the service configs are properly updated, when the services restart they will return a cert with the SAN `DNS:*.example.test`, which is valid for `mail.example.test`, however the test function did not properly account for this in the regexp query. Resolved by truncating the left-most DNS label from FQDN and adding a third check to match a returned wildcard DNS result. Extracted out the common logic to create the regexp query and renamed the methods to communicate more clearly that they check the FQDN is supported, not necessarily explicitly listed by the cert. * tests(letsencrypt): Enable remaining tests These will now pass. Adjusted comments accordingly. Added an additional test on a fake FQDN that should still be valid to a wildcard cert (SNI validation in a proper setup would reject the connection afterwards). Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
2022-04-18 12:52:50 +02:00
# mark changes as applied
mv "${CHKSUM_FILE}.new" "${CHKSUM_FILE}"
fi
}
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
function _handle_changes() {
# Variable to identify any config updates dependent upon vhost changes.
local VHOST_UPDATED=0
# These two configs are the source for /etc/postfix/vhost (managed mail domains)
if [[ ${CHANGED} =~ ${DMS_DIR}/postfix-(accounts|virtual).cf ]]; then
_log 'trace' 'Regenerating vhosts (Postfix)'
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
# Regenerate via `helpers/postfix.sh`:
_create_postfix_vhost
VHOST_UPDATED=1
fi
_ssl_changes
_postfix_dovecot_changes
_rspamd_changes
_log 'debug' 'Reloading services due to detected changes'
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
[[ ${ENABLE_AMAVIS} -eq 1 ]] && _reload_amavis
_reload_postfix
[[ ${SMTP_ONLY} -ne 1 ]] && dovecot reload
}
2023-05-26 01:01:41 +02:00
function _get_changed_files() {
local CHKSUM_CURRENT=${1}
local CHKSUM_NEW=${2}
# Diff the two files for lines that don't match or differ from lines in CHKSUM_FILE
# grep -Fxvf
# -f use CHKSUM_FILE lines as input patterns to match for
# -F The patterns to match are treated as strings only, not treated as regex syntax
# -x (match whole lines only)
# -v invert the matching so only non-matches are output
# Extract file paths by truncating the matched content hash and white-space from lines:
# sed -r 's/^\S+[[:space:]]+//'
grep -Fxvf "${CHKSUM_CURRENT}" "${CHKSUM_NEW}" | sed -r 's/^\S+[[:space:]]+//'
}
2023-05-26 01:01:41 +02:00
function _reload_amavis() {
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
# /etc/postfix/vhost was updated, amavis must refresh it's config by
# reading this file again in case of new domains, otherwise they will be ignored.
if [[ ${VHOST_UPDATED} -eq 1 ]]; then
amavisd reload
fi
}
# Also note that changes are performed in place and are not atomic
# We should fix that and write to temporary files, stop, swap and start
2023-05-26 01:01:41 +02:00
function _postfix_dovecot_changes() {
local DMS_DIR=/tmp/docker-mailserver
# Regenerate accounts via `helpers/accounts.sh`:
# - dovecot-quotas.cf used by _create_accounts + _create_dovecot_alias_dummy_accounts
# - postfix-virtual.cf used by _create_dovecot_alias_dummy_accounts (only when ENABLE_QUOTAS=1)
if [[ ${CHANGED} =~ ${DMS_DIR}/postfix-accounts.cf ]] \
|| [[ ${CHANGED} =~ ${DMS_DIR}/postfix-virtual.cf ]] \
|| [[ ${CHANGED} =~ ${DMS_DIR}/postfix-aliases.cf ]] \
|| [[ ${CHANGED} =~ ${DMS_DIR}/dovecot-quotas.cf ]] \
|| [[ ${CHANGED} =~ ${DMS_DIR}/dovecot-masters.cf ]]
then
_log 'trace' 'Regenerating accounts (Dovecot + Postfix)'
fix: `check-for-changes.sh` should not fall out of sync with shared logic (#2260) Removes duplicate logic from `check-for-changes.sh` that is used/maintained elsewhere to avoid risk of problems, as this code is already starting to diverge / rot. --- Previously the change detection support has had code added for rebuilding config upon change detection which is the same as code run during startup scripts. Unfortunately over time this has fallen out of sync. Mostly the startup scripts would get maintenance and the contributor and reviewers may not have been aware of the duplicate code handled by `check-for-changes.sh`. That code was starting to diverge in addition to some changes in structure (_eg: relay host logic seems interleaved here vs separated out in startup scripts_). I wanted to address this before it risks becoming a much bigger headache. Rather than bloat `helper-functions.sh` further, I've added a `helpers/` folder extracting relevant common logic between startup scripts and `changedetector`. If you want to follow that process I've kept scoped commits to make those diffs easier. Some minor changes/improvements were added but nothing significant. --- - chore: Extract relay host logic to new `relay.sh` helper - chore: Extract `/etc/postfix/sasl_passwd` logic to new `sasl.sh` helper - chore: Extract `postfix-accounts.cf` logic to new `accounts.sh` helper - chore: Extract `/etc/aliases` logic to new `aliases.sh` helper - chore: Extract `/etc/postfix/vhost` logic to new `postfix.sh` helper - chore: Add inline docs for Postfix configs > These are possibly more verbose than needed and can be reduced at a later stage. > They are helpful during this refactor process while investigating that everything is handled correctly. `accounts.sh`: - Add note regarding potential bug for bare domain setups with `/etc/postfix/vhost` and `mydestination` sharing same domain value. `relay.sh`: - Remove the tabs for a single space delimiter, revised associated comment. - Add PR reference for original `_populate_relayhost_map` implementation which has some useful details. Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Co-authored-by: Casper <casperklein@users.noreply.github.com>
2021-11-20 21:33:49 +01:00
[[ ${SMTP_ONLY} -ne 1 ]] && _create_accounts
fi
# Regenerate relay config via `helpers/relay.sh`:
# - postfix-sasl-password.cf used by _relayhost_sasl
# - _populate_relayhost_map relies on:
# - postfix-relaymap.cf
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
if [[ ${VHOST_UPDATED} -eq 1 ]] \
|| [[ ${CHANGED} =~ ${DMS_DIR}/postfix-relaymap.cf ]] \
|| [[ ${CHANGED} =~ ${DMS_DIR}/postfix-sasl-password.cf ]]
then
_log 'trace' 'Regenerating relay config (Postfix)'
refactor: `relay.sh` (#3845) * chore: `relay.sh` helper - Reference user config paths via variables * chore: Better document postfix helper `_vhost_collect_postfix_domains()` The functionality is effectively the same for the two configs for the most part when it comes to parsing out a domain from the target value. Virtual aliases is more flexible in value, which may not have a domain-part present (manual user edit). * chore: `check-for-change.sh` - Support VHOST change visibility - Moves the "handle changes" logic into it's own scoped function, out of the main change detection loop logic. - This will be benefit a future commit change that will rely on `VHOST_UPDATED=1`. * chore: `relay.sh` - Minor revisions to minimize diff noise - Better phrasing of the current logic comments. - Regex patterns assigned to variables (easier to grok intention) - Bulk of the logic for generating `/etc/postfix/relayhost_map` wrapped into a separate function with Postfix config setting handled separately. * refactor: `relay.sh` opt-out logic - Split the two distinct features that configure `/etc/postfix/relayhost_map` into separate functions (_`MATCH_VALID` var no longer needed for legacy support_). - Instead of extracting domains from `postfix-accounts.cf` + `postfix-virtual.cf`, this has already been handled at `/etc/postfix/vhost`, sourcing from there is far less complicated. - Rename loop var `DOMAIN_PART`to `SENDER_DOMAIN` for better context of what it represents when appended to the config file. - Revised maintenance notes + guidance towards a future refactor of this relayhost feature support. * docs: `relay.sh` - Additional comment revisions * feat: `DEFAULT_RELAY_HOST` can now also use relay credentials ENV - Remove comment regarding `smtp_sasl_password_maps = static:${RELAY_USER}:${RELAY_PASSWORD}`, it could be used but `main.cf` presently has `644` permissions vs the `sasl_passwd` file permissions of `600`, less secure at preventing leaking of secrets (ignoring the ENV exposure itself). - Move the `main.cf` settings specific to relayhost credentials support / security into to the relevant function scope instead. This also allows for the configuration to be applied by a change detection event without container restart requirement. - Outer functions for setup and change detection to call have a clearer config dependency guard, as does the `_legacy_support()`. - These changes now support `DEFAULT_RELAY_HOST` to leverage the relay credentials ENV as well. - `DATABASE_RELAYHOSTS` is available in scope to the functions called here that reference it. * docs: Revised ENV docs on relay host config Better quality guidance on configuring relay hosts. * chore: Add entry to `CHANGELOG.md` * fix: `relay.sh` - `grep` regex compatibility with `+` requires `-E` * chore: `postfix.sh` - `FIRST_FIELD` => More descriptive field name
2024-01-30 22:24:43 +01:00
_process_relayhost_configs
fi
# Regenerate system + virtual account aliases via `helpers/aliases.sh`:
[[ ${CHANGED} =~ ${DMS_DIR}/postfix-virtual.cf ]] && _handle_postfix_virtual_config
[[ ${CHANGED} =~ ${DMS_DIR}/postfix-regexp.cf ]] && _handle_postfix_regexp_config
[[ ${CHANGED} =~ ${DMS_DIR}/postfix-aliases.cf ]] && _handle_postfix_aliases_config
2019-08-01 19:39:25 +02:00
# Legacy workaround handled here, only seems necessary for _create_accounts:
# - `helpers/accounts.sh` logic creates folders/files with wrong ownership.
_chown_var_mail_if_necessary
}
2023-05-26 01:01:41 +02:00
function _ssl_changes() {
local REGEX_NEVER_MATCH='(?\!)'
# _setup_ssl is required for:
# manual - copy to internal DMS_TLS_PATH (/etc/dms/tls) that Postfix and Dovecot are configured to use.
# acme.json - presently uses /etc/letsencrypt/live/<FQDN> instead of DMS_TLS_PATH,
# path may change requiring Postfix/Dovecot config update.
2023-05-24 09:06:59 +02:00
if [[ ${SSL_TYPE} == 'manual' ]]; then
# only run the SSL setup again if certificates have really changed.
if [[ ${CHANGED} =~ ${SSL_CERT_PATH:-${REGEX_NEVER_MATCH}} ]] \
|| [[ ${CHANGED} =~ ${SSL_KEY_PATH:-${REGEX_NEVER_MATCH}} ]] \
|| [[ ${CHANGED} =~ ${SSL_ALT_CERT_PATH:-${REGEX_NEVER_MATCH}} ]] \
|| [[ ${CHANGED} =~ ${SSL_ALT_KEY_PATH:-${REGEX_NEVER_MATCH}} ]]
then
_log 'debug' 'Manual certificates have changed - extracting certificates'
_setup_ssl
fi
# `acme.json` is only relevant to Traefik, and is where it stores the certificates it manages.
# When a change is detected it's assumed to be a possible cert renewal that needs to be
# extracted for `docker-mailserver` services to adjust to.
2023-05-24 09:06:59 +02:00
elif [[ ${CHANGED} =~ /etc/letsencrypt/acme.json ]]; then
_log 'debug' "'/etc/letsencrypt/acme.json' has changed - extracting certificates"
_setup_ssl
# Prevent an unnecessary change detection from the newly extracted cert files by updating their hashes in advance:
local CERT_DOMAIN ACME_CERT_DIR
CERT_DOMAIN=$(_find_letsencrypt_domain)
ACME_CERT_DIR="/etc/letsencrypt/live/${CERT_DOMAIN}"
sed -i "\|${ACME_CERT_DIR}|d" "${CHKSUM_FILE}.new"
sha512sum "${ACME_CERT_DIR}"/*.pem >> "${CHKSUM_FILE}.new"
fi
# If monitored certificate files in /etc/letsencrypt/live have changed and no `acme.json` is in use,
# They presently have no special handling other than to trigger a change that will restart Postfix/Dovecot.
refactor: letsencrypt implicit location discovery (#2525) * chore: Extract letsencrypt logic into methods This allows other scripts to share the functionality to discover the correct letsencrypt folder from the 3 possible locations (where specific order is important). As these methods should now return a string value, the `return 1` after a panic is now dropped. * chore: Update comments The todo is resolved with this PR, `_setup_ssl` will be called by both cert conditional statements with purpose for each better documented to maintainers at the start of the logic block. * refactor: Defer most logic to helper/ssl.sh The loop is no longer required, extraction is delegated to `_setup_ssl` now. For the change event prevention, we retrieve the relevant FQDN via the new helper method, beyond that it's just indentation diff. `check-for-changes.sh` adjusted to allow locally scoped var declarations by wrapping a function. Presently no loop control flow is needed so this seems fine. Made it clear that `CHANGED` is local and `CHKSUM_FILE` is not. Panic scope doesn't require `SSL_TYPE` for context, it's clearly`letsencrypt`. * fix: Correctly match wildcard results Now that the service configs are properly updated, when the services restart they will return a cert with the SAN `DNS:*.example.test`, which is valid for `mail.example.test`, however the test function did not properly account for this in the regexp query. Resolved by truncating the left-most DNS label from FQDN and adding a third check to match a returned wildcard DNS result. Extracted out the common logic to create the regexp query and renamed the methods to communicate more clearly that they check the FQDN is supported, not necessarily explicitly listed by the cert. * tests(letsencrypt): Enable remaining tests These will now pass. Adjusted comments accordingly. Added an additional test on a fake FQDN that should still be valid to a wildcard cert (SNI validation in a proper setup would reject the connection afterwards). Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
2022-04-18 12:52:50 +02:00
}
function _rspamd_changes() {
# RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd'
if [[ ${CHANGED} =~ ${RSPAMD_DMS_D}/.* ]]; then
# "${RSPAMD_DMS_D}/override.d"
if [[ ${CHANGED} =~ ${RSPAMD_DMS_OVERRIDE_D}/.* ]]; then
_log 'trace' 'Rspamd - Copying configuration overrides'
rm "${RSPAMD_OVERRIDE_D}"/*
cp "${RSPAMD_DMS_OVERRIDE_D}"/* "${RSPAMD_OVERRIDE_D}"
fi
# "${RSPAMD_DMS_D}/custom-commands.conf"
if [[ ${CHANGED} =~ ${RSPAMD_DMS_CUSTOM_COMMANDS_F} ]]; then
_log 'trace' 'Rspamd - Generating new configuration from custom commands'
_rspamd_handle_user_modules_adjustments
fi
# "${RSPAMD_DMS_D}/dkim"
if [[ ${CHANGED} =~ ${RSPAMD_DMS_DKIM_D} ]]; then
_log 'trace' 'Rspamd - DKIM files updated'
fi
_log 'debug' 'Rspamd configuration has changed - restarting service'
supervisorctl restart rspamd
fi
}
2023-05-26 01:39:39 +02:00
while true; do
refactor: letsencrypt implicit location discovery (#2525) * chore: Extract letsencrypt logic into methods This allows other scripts to share the functionality to discover the correct letsencrypt folder from the 3 possible locations (where specific order is important). As these methods should now return a string value, the `return 1` after a panic is now dropped. * chore: Update comments The todo is resolved with this PR, `_setup_ssl` will be called by both cert conditional statements with purpose for each better documented to maintainers at the start of the logic block. * refactor: Defer most logic to helper/ssl.sh The loop is no longer required, extraction is delegated to `_setup_ssl` now. For the change event prevention, we retrieve the relevant FQDN via the new helper method, beyond that it's just indentation diff. `check-for-changes.sh` adjusted to allow locally scoped var declarations by wrapping a function. Presently no loop control flow is needed so this seems fine. Made it clear that `CHANGED` is local and `CHKSUM_FILE` is not. Panic scope doesn't require `SSL_TYPE` for context, it's clearly`letsencrypt`. * fix: Correctly match wildcard results Now that the service configs are properly updated, when the services restart they will return a cert with the SAN `DNS:*.example.test`, which is valid for `mail.example.test`, however the test function did not properly account for this in the regexp query. Resolved by truncating the left-most DNS label from FQDN and adding a third check to match a returned wildcard DNS result. Extracted out the common logic to create the regexp query and renamed the methods to communicate more clearly that they check the FQDN is supported, not necessarily explicitly listed by the cert. * tests(letsencrypt): Enable remaining tests These will now pass. Adjusted comments accordingly. Added an additional test on a fake FQDN that should still be valid to a wildcard cert (SNI validation in a proper setup would reject the connection afterwards). Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
2022-04-18 12:52:50 +02:00
_check_for_changes
sleep 2
done
2021-02-24 17:28:59 +01:00
exit 0