#!/bin/sh -e # # 2021 Joachim Desroches (joachim.desroches@epfl.ch) # # This file is part of cdist. # # cdist is free software: 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. # # cdist is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # 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 contribute an implementation for $os if you can. EOF exit 1 ;; esac # Logic to simplify the type as documented in # https://code.ungleich.ch/ungleich-public/cdist-contrib/issues/20#issuecomment-14711 DOMAIN="$(cat "${__object:?}/parameter/domain" 2>/dev/null || true)" SELECTOR="$(cat "${__object:?}/parameter/selector" 2>/dev/null || true)" if [ -z "${DOMAIN}${SELECTOR}" ]; then # Neither SELECTOR nor DOMAIN were passed, try to use __object_id if echo "${__object_id:?}" | \ grep -qE '^[^/[:space:]]+/[^/[:space:]]+$'; then # __object_id matches, let's get the data DOMAIN="$(echo "${__object_id:?}" | cut -d '/' -f 1)" SELECTOR="$(echo "${__object_id:?}" | cut -d '/' -f 2)" else # It doesn't match the pattern, this is sad cat <<- EOF >&2 The arguments --domain and --selector were not used. So __object_id must match DOMAIN/SELECTOR. But instead the type got: ${__object_id:?} EOF exit 1 fi elif [ -z "${DOMAIN}" ] || [ -z "${SELECTOR}" ]; then # Only one was passed, this is sad :-( cat <<- EOF >&2 You must pass either both --selector and --domain or none of them. If these arguments are absent, __object_id must match: DOMAIN/SELECTOR. EOF exit 1 # else: both were passed fi # Persist data for gencode-remote printf '%s' "${user:?}" > "${__object:?}/user" printf '%s' "${group:?}" > "${__object:?}/group" printf '%s' "${DOMAIN:?}" > "${__object:?}/domain" printf '%s' "${SELECTOR:?}" > "${__object:?}/selector" DIRECTORY="/var/db/dkim/" if [ -f "${__object:?}/parameter/directory" ]; then # Be forgiving about a lack of trailing slash DIRECTORY="$(sed -E 's!([^/])$!\1/!' < "${__object:?}/parameter/directory")" fi SIGKEY="${DOMAIN:?}" if [ -f "${__object:?}/parameter/sigkey" ]; then SIGKEY="$(cat "${__object:?}/parameter/sigkey")" fi SIGDOMAIN="${DOMAIN:?}" if [ -f "${__object:?}/parameter/sigdomain" ]; then SIGDOMAIN="$(cat "${__object:?}/parameter/sigdomain")" fi # Ensure the key-container directory exists with the proper permissions __directory "${DIRECTORY}" \ --mode 0750 \ --owner "${user}" --group "${group}" # OS-specific code case "$os" in 'alpine') # This is needed for opendkim-genkey __package opendkim-utils ;; esac key_table="${CFG_DIR}/KeyTable" signing_table="${CFG_DIR}/SigningTable" KEY_STATE="$(cut -f 1 "${__object:?}/explorer/key-state")" KEY_LOCATION="$(cut -f 2- "${__object:?}/explorer/key-state")" __line "__opendkim_genkey/${__object_id:?}" \ --file "${key_table}" \ --line "${__object_id:?} ${SIGDOMAIN:?}:${SELECTOR:?}:${KEY_LOCATION:?}" \ --regex "^${__object_id:?}[[:space:]]" \ --state 'replace' sigtable_block() { for sigkey in ${SIGKEY:?}; do echo "${sigkey:?} ${__object_id:?}" done } __block "__opendkim_genkey/${__object_id:?}" \ --file "${signing_table}" \ --text "$(sigtable_block)" if [ "${KEY_STATE:?}" = "present" ]; then # Ensure proper permissions for the key file __file "${KEY_LOCATION}" \ --owner "${user}" \ --group "${group}" \ --mode 0600 fi