From ecd10de2d3517be874ac5b54b4c03214afe12672 Mon Sep 17 00:00:00 2001 From: Evilham Date: Thu, 10 Mar 2022 20:08:51 +0100 Subject: [PATCH] [__opendkim*] FreeBSD support and minor fixes While adding FreeBSD support to the type I noticed various issues: - We were making sure that the KeyTable and SigningTable were created in __opendkim_genkey, but that was being done with the default cdist permissions (0400) which could result in issues when reloading the service after privilege drop. This is addressed by checking that it exists/creating it in __opendkim (just once, not once per __opendkim_genkey call) with laxer permissions (0444). - In __opendkim, the service was being started after the config file was installed. This is insufficient as OpenDKIM will refuse to start with the generated config if either SigningTable or KeyTable do not exist yet. - __opendkim_genkey had the implicit assumption that the --directory parameter always ended in a slash. This was not documented and error-prone; we are now a bit laxer and add the trailing slash if it is missing. - __opendkim_genkey was not changing permissions for the resulting .txt file. This was not critical for it to function, but it was inconsistent. - As documented in #17, __opendkim allows for a --userid parameter that might cause issues with keys generated by __opendkim_genkey. This issue has not been addressed yet, but I recommend deprecating the --userid parameter. --- type/__opendkim/files/opendkim.conf.sh | 5 +-- type/__opendkim/man.rst | 12 ++++--- type/__opendkim/manifest | 28 ++++++++++++--- type/__opendkim_genkey/gencode-remote | 10 ++++-- type/__opendkim_genkey/man.rst | 7 ++-- type/__opendkim_genkey/manifest | 47 ++++++++++++++++++-------- 6 files changed, 79 insertions(+), 30 deletions(-) diff --git a/type/__opendkim/files/opendkim.conf.sh b/type/__opendkim/files/opendkim.conf.sh index a21eecc..468b262 100755 --- a/type/__opendkim/files/opendkim.conf.sh +++ b/type/__opendkim/files/opendkim.conf.sh @@ -1,6 +1,7 @@ #!/bin/sh -e # Generate an opendkim.conf(5) file for opendkim(8). +echo "# Managed remotely, manual changes will be lost." # Optional chdir(2) if [ "$BASEDIR" ]; @@ -33,8 +34,8 @@ then fi # Key and Domain tables -echo 'KeyTable /etc/opendkim/KeyTable' -echo 'SigningTable /etc/opendkim/SigningTable' +echo "KeyTable ${CFG_DIR}/KeyTable" +echo "SigningTable ${CFG_DIR}/SigningTable" # Required socket to listen on printf "Socket %s\n" "${SOCKET:?}" diff --git a/type/__opendkim/man.rst b/type/__opendkim/man.rst index 205ca65..e3f3e7a 100644 --- a/type/__opendkim/man.rst +++ b/type/__opendkim/man.rst @@ -14,8 +14,8 @@ installation and basic configuration of an instance of OpenDKIM. Note that this type does not generate or ensure that a key is present: use `cdist-type__opendkim-genkey(7)` for that. -Note that this type is currently only implemented for Alpine Linux. Please -contribute an implementation if you can. +Note that this type is currently only implemented for Alpine Linux and FreeBSD. +Please contribute an implementation if you can. REQUIRED PARAMETERS @@ -42,8 +42,9 @@ umask Set the umask for the socket and PID file. userid - Change the user the opendkim program is to run as. By default, Alpine Linux's - OpenRC service will set this to `opendkim` on the command-line. + Change the user the opendkim program is to run as. + By default, Alpine Linux's OpenRC service will set this to `opendkim` on the + command-line and FreeBSD's rc will set it to `mailnull`. custom-config The string following this parameter is appended as-is in the configuration, to @@ -86,11 +87,12 @@ SEE ALSO AUTHORS ------- Joachim Desroches +Evilham COPYING ------- -Copyright \(C) 2021 Joachim Desroches. You can redistribute it +Copyright \(C) 2022 Joachim Desroches, Evilham. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/type/__opendkim/manifest b/type/__opendkim/manifest index e3325b4..dbd9fc0 100755 --- a/type/__opendkim/manifest +++ b/type/__opendkim/manifest @@ -20,16 +20,23 @@ os=$(cat "${__global:?}/explorer/os") +CFG_DIR="/etc/opendkim" +service="opendkim" case "$os" in 'alpine') : ;; +'freebsd') + CFG_DIR="/usr/local/etc/mail" + service="milter-opendkim" + ;; *) printf "__opendkim does not yet support %s.\n" "$os" >&2 printf "Please contribute an implementation if you can.\n" >&2 exit 1 ;; esac +export CFG_DIR __package opendkim @@ -68,7 +75,7 @@ fi # Generate and deploy configuration file. source_file="${__object:?}/files/opendkim.conf" -target_file="/etc/opendkim/opendkim.conf" +target_file="${CFG_DIR}/opendkim.conf" mkdir -p "${__object:?}/files" @@ -83,9 +90,22 @@ fi require="__package/opendkim" __file "$target_file" \ --source "$source_file" --mode 0644 -require="__package/opendkim" __start_on_boot opendkim +require="__package/opendkim" __start_on_boot "${service}" -require="__file${target_file}" \ +# Ensure Key and Signing tables exist and have proper permissions +key_table="${CFG_DIR}/KeyTable" +signing_table="${CFG_DIR}/SigningTable" + +require="__package/opendkim" \ + __file "${key_table}" \ + --mode 444 + +require="__package/opendkim" \ + __file "${signing_table}" \ + --mode 444 + +require="__file${target_file} __file${key_table} + __file${signing_table} __start_on_boot/${service}" \ __check_messages opendkim \ --pattern "^__file${target_file}" \ - --execute "service opendkim restart" + --execute "service ${service} restart" diff --git a/type/__opendkim_genkey/gencode-remote b/type/__opendkim_genkey/gencode-remote index 65ce934..d8dfb4d 100755 --- a/type/__opendkim_genkey/gencode-remote +++ b/type/__opendkim_genkey/gencode-remote @@ -30,7 +30,8 @@ fi DIRECTORY="/var/db/dkim/" if [ -f "${__object:?}/parameter/directory" ]; then - DIRECTORY="$(cat "${__object:?}/parameter/directory")" + # Be forgiving about a lack of trailing slash + DIRECTORY="$(sed -E 's!([^/])$!\1/!' < "${__object:?}/parameter/directory")" fi # Boolean parameters @@ -44,7 +45,12 @@ if [ -f "${__object:?}/parameters/unrestricted" ]; then RESTRICTED= fi +user="$(cat "${__object:?}/user")" +group="$(cat "${__object:?}/group")" + if ! [ -f "${DIRECTORY}${SELECTOR}.private" ]; then echo "opendkim-genkey $BITS --domain=$DOMAIN --directory=$DIRECTORY $RESTRICTED --selector=$SELECTOR $SUBDOMAINS" - echo "chown opendkim:opendkim ${DIRECTORY}${SELECTOR}.private" + echo "chown ${user}:${group} ${DIRECTORY}${SELECTOR}.private" + # This is usually generated, if it weren't we do not want to fail + echo "chown ${user}:${group} ${DIRECTORY}${SELECTOR}.txt || true" fi diff --git a/type/__opendkim_genkey/man.rst b/type/__opendkim_genkey/man.rst index 46e6505..b3fd013 100644 --- a/type/__opendkim_genkey/man.rst +++ b/type/__opendkim_genkey/man.rst @@ -17,8 +17,8 @@ will be added to the OpenDKIM signing table, using either the domain or the provided key for the `domain:selector:keyfile` value in the table. An existing key will not be overwritten. -Currently, this type is only implemented for Alpine Linux. Please contribute an -implementation if you can. +Currently, this type is only implemented for Alpine Linux and FreeBSD. +Please contribute an implementation if you can. REQUIRED PARAMETERS ------------------- @@ -85,11 +85,12 @@ SEE ALSO AUTHORS ------- Joachim Desroches +Evilham COPYING ------- -Copyright \(C) 2021 Joachim Desroches. You can redistribute it +Copyright \(C) 2022 Joachim Desroches, Evilham. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/type/__opendkim_genkey/manifest b/type/__opendkim_genkey/manifest index 7c506e9..50dcee5 100755 --- a/type/__opendkim_genkey/manifest +++ b/type/__opendkim_genkey/manifest @@ -21,10 +21,18 @@ os=$(cat "${__global:?}/explorer/os") +CFG_DIR="/etc/opendkim" +user="opendkim" +group="opendkim" case "$os" in 'alpine') : ;; +'freebsd') + CFG_DIR="/usr/local/etc/mail" + user="mailnull" + group="mailnull" +;; *) cat <<- EOF >&2 __opendkim_genkey currently only supports Alpine Linux. Please @@ -32,6 +40,9 @@ case "$os" in EOF ;; esac +# Persist user and group for gencode-remote +printf '%s' "${user}" > "${__object:?}/user" +printf '%s' "${group}" > "${__object:?}/group" SELECTOR="$(cat "${__object:?}/parameter/selector")" DOMAIN="$(cat "${__object:?}/parameter/domain")" @@ -39,7 +50,8 @@ DOMAIN="$(cat "${__object:?}/parameter/domain")" DIRECTORY="/var/db/dkim/" if [ -f "${__object:?}/parameter/directory" ]; then - DIRECTORY="$(cat "${__object:?}/parameter/directory")" + # Be forgiving about a lack of trailing slash + DIRECTORY="$(sed -E 's!([^/])$!\1/!' < "${__object:?}/parameter/directory")" fi SIGKEY="${DOMAIN:?}" @@ -48,19 +60,26 @@ then SIGKEY="$(cat "${__object:?}/parameter/sigkey")" fi -__package opendkim-utils +# Ensure the key-container directory exists with the proper permissions +__directory "${DIRECTORY}" \ + --mode 0750 \ + --owner "${user}" --group "${group}" -require='__package/opendkim-utils' \ - __file /etc/opendkim/KeyTable -require='__package/opendkim-utils' \ - __file /etc/opendkim/SigningTable +# OS-specific code +case "$os" in +'alpine') + # This is needed for opendkim-genkey + __package opendkim-utils +;; +esac -require='__file/etc/opendkim/KeyTable' \ - __line "line-key-${__object_id:?}" \ - --file /etc/opendkim/KeyTable \ - --line "${SELECTOR:?}._domainkey.${DOMAIN:?} ${DOMAIN:?}:${SELECTOR:?}:${DIRECTORY:?}${SELECTOR:?}.private" +key_table="${CFG_DIR}/KeyTable" +signing_table="${CFG_DIR}/SigningTable" -require='__file/etc/opendkim/SigningTable' \ - __line "line-sig-${__object_id:?}" \ - --file /etc/opendkim/SigningTable \ - --line "${SIGKEY:?} ${SELECTOR:?}._domainkey.${DOMAIN:?}" +__line "line-key-${__object_id:?}" \ + --file "${key_table}" \ + --line "${SELECTOR:?}._domainkey.${DOMAIN:?} ${DOMAIN:?}:${SELECTOR:?}:${DIRECTORY:?}${SELECTOR:?}.private" + +__line "line-sig-${__object_id:?}" \ + --file "${signing_table}" \ + --line "${SIGKEY:?} ${SELECTOR:?}._domainkey.${DOMAIN:?}"