Merge branch 'dma-type' into 'master'
Add __mail_alias, __dma* types See merge request ungleich-public/cdist-contrib!6
This commit is contained in:
commit
f4375dbbb9
30 changed files with 1357 additions and 9 deletions
|
@ -1,21 +1,29 @@
|
||||||
#!/bin/sh
|
#!/bin/sh -eu
|
||||||
|
|
||||||
SHELLCHECKCMD="shellcheck -s sh -f gcc -x"
|
SHELLCHECKCMD='shellcheck -s sh -f gcc -x'
|
||||||
# Skip SC2154 for variables starting with __ since such variables are cdist
|
# Skip SC2154 for variables starting with __ since such variables are cdist
|
||||||
# environment variables.
|
# environment variables.
|
||||||
SHELLCHECK_SKIP=': __.*is referenced but not assigned.*\[SC2154\]'
|
SHELLCHECK_SKIP=': __.*is referenced but not assigned.*\[SC2154\]'
|
||||||
SHELLCHECKTMP=".shellcheck.tmp"
|
SHELLCHECKTMP='.shellcheck.tmp'
|
||||||
|
|
||||||
# Move to top-level cdist-contrib directory.
|
# Move to top-level cdist-contrib directory.
|
||||||
cd $(dirname $0)/..
|
cd "$(dirname $0)"/..
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
find type/ -type f $1 $2 -exec ${SHELLCHECKCMD} {} + | grep -v "${SHELLCHECK_SKIP}" > "${SHELLCHECKTMP}"
|
find type/ -type f "$@" -exec ${SHELLCHECKCMD} {} + \
|
||||||
test ! -s "${SHELLCHECKTMP}" || { cat "${SHELLCHECKTMP}"; exit 1; }
|
| grep -v "${SHELLCHECK_SKIP}" >>"${SHELLCHECKTMP}" || true
|
||||||
}
|
}
|
||||||
|
|
||||||
check -path "*/explorer/*"
|
rm -f "${SHELLCHECKTMP}"
|
||||||
check -path "*/files/*.sh"
|
|
||||||
|
check -path '*/explorer/*'
|
||||||
|
check -path '*/files/*' -name '*.sh'
|
||||||
check -name manifest
|
check -name manifest
|
||||||
check -name gencode-local
|
check -name gencode-local
|
||||||
check -name gencode-remote
|
check -name gencode-remote
|
||||||
|
|
||||||
|
if test -s "${SHELLCHECKTMP}"
|
||||||
|
then
|
||||||
|
cat "${SHELLCHECKTMP}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
49
type/__dma/explorer/auth_conf
Executable file
49
type/__dma/explorer/auth_conf
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# This explorer determines the path of dma's auth.conf file
|
||||||
|
|
||||||
|
# No dma.conf -> use default
|
||||||
|
test -f /etc/dma/dma.conf || {
|
||||||
|
echo /etc/dma/auth.conf
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
test -r /etc/dma/dma.conf || {
|
||||||
|
echo 'Cannot read /etc/dma/dma.conf' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get AUTHPATH from dma.conf
|
||||||
|
awk -F'[ \t]' '
|
||||||
|
{
|
||||||
|
sub(/#.*$/, "", $0) # remove comments
|
||||||
|
if (!$0) next # ignore empty lines
|
||||||
|
}
|
||||||
|
$1 == "AUTHPATH" {
|
||||||
|
# Store authpath. In dma conf parsing last wins.
|
||||||
|
if ($2) authpath = substr($0, index($0, " ") + 1)
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (authpath) {
|
||||||
|
print authpath
|
||||||
|
exit 0
|
||||||
|
} else exit 1
|
||||||
|
}
|
||||||
|
' /etc/dma/dma.conf \
|
||||||
|
|| echo /etc/dma/auth.conf # default
|
34
type/__dma/explorer/conf
Executable file
34
type/__dma/explorer/conf
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# This explorer returns a sorted list of "active" (= non-commented) lines
|
||||||
|
# in the dma.conf file.
|
||||||
|
# "Trailing" line comments are stripped off.
|
||||||
|
#
|
||||||
|
# NOTE: This explorer assumes that the sort(1) utility supports the non-POXIX
|
||||||
|
# -s (stable sort) option.
|
||||||
|
|
||||||
|
CONF_PATH=/etc/dma # set in Makefile
|
||||||
|
dma_conf="${CONF_PATH:?}/dma.conf"
|
||||||
|
|
||||||
|
test -f "${dma_conf}" || exit 0
|
||||||
|
|
||||||
|
grep -v -e '^[ \t]*#\|^$' "${dma_conf}" \
|
||||||
|
| sed -e 's/[ \t]*#.*$//' \
|
||||||
|
| sort -s -k 1,1
|
178
type/__dma/files/update_dma_conf.awk
Normal file
178
type/__dma/files/update_dma_conf.awk
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
#!/usr/bin/awk -f
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
function comment_line(line) {
|
||||||
|
# returns the position in line at which the comment's text starts
|
||||||
|
# (0 if the line is not a comment)
|
||||||
|
match(line, /^[ \t]*\#+[ \t]*/)
|
||||||
|
return RSTART ? (RLENGTH + 1) : 0
|
||||||
|
}
|
||||||
|
function empty_line(line) { return line ~ /^[ \t]*$/ }
|
||||||
|
function is_word(s) { return s ~ /^[A-Z_]+$/ } # "looks like a plausible word"
|
||||||
|
|
||||||
|
function first(line, sep_re) {
|
||||||
|
# returns the part of the line until sep is found
|
||||||
|
# (or the whole line if sep is not found)
|
||||||
|
if (!sep_re) sep_re = "[" SUBSEP "]"
|
||||||
|
match(line, sep_re)
|
||||||
|
return RSTART ? substr(line, 1, RSTART - 1) : line
|
||||||
|
}
|
||||||
|
|
||||||
|
function rest(line, sep_re) {
|
||||||
|
# returns the part of the line after the first occurrence of sep is found.
|
||||||
|
# (or nothing if sep is not found)
|
||||||
|
if (!sep_re) sep_re = "[" SUBSEP "]"
|
||||||
|
if (match(line, sep_re))
|
||||||
|
return substr(line, RSTART + RLENGTH)
|
||||||
|
}
|
||||||
|
|
||||||
|
function conf_pop(word, value) {
|
||||||
|
# returns the next value for the config `word` and delete it from the list.
|
||||||
|
# if value is set, this function will only return value if it is the first
|
||||||
|
# option in the list, otherwise it returns 0.
|
||||||
|
|
||||||
|
if (!(word in conf)) return 0
|
||||||
|
if (!value) {
|
||||||
|
if (index(conf[word], SUBSEP)) # more than one element?
|
||||||
|
value = substr(conf[word], 1, index(conf[word], SUBSEP) - 1)
|
||||||
|
else
|
||||||
|
value = conf[word]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index(conf[word], SUBSEP)) {
|
||||||
|
if (index(conf[word], value SUBSEP) != 1) return 0
|
||||||
|
conf[word] = substr(conf[word], length(value) + 2)
|
||||||
|
} else {
|
||||||
|
if (conf[word] != value) return 0
|
||||||
|
delete conf[word]
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_conf(word, value) {
|
||||||
|
# print a config line with the given parameters
|
||||||
|
printf "%s", word
|
||||||
|
if (value) printf " %s", value
|
||||||
|
printf "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_confs(word, value) {
|
||||||
|
# print config lines for all values stored in conf[word].
|
||||||
|
if (!(word in conf)) return
|
||||||
|
if (conf[word]) {
|
||||||
|
while (value = conf_pop(word))
|
||||||
|
print_conf(word, value)
|
||||||
|
} else {
|
||||||
|
print_conf(word)
|
||||||
|
delete conf[word]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
FS = "\n"
|
||||||
|
EQS = "[ \t]" # copied from dma/conf.c
|
||||||
|
|
||||||
|
if (ARGV[2]) exit (e=1)
|
||||||
|
|
||||||
|
# Loop over file twice!
|
||||||
|
ARGV[2] = ARGV[1]
|
||||||
|
ARGC++
|
||||||
|
|
||||||
|
# read the "should" state into the `conf` array.
|
||||||
|
while (getline < "/dev/stdin") {
|
||||||
|
word = first($0, EQS)
|
||||||
|
if ((word in conf))
|
||||||
|
conf[word] = conf[word] SUBSEP rest($0, EQS)
|
||||||
|
else
|
||||||
|
conf[word] = rest($0, EQS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# first pass, gather information about where which information is stored in the
|
||||||
|
# current config file. This information will be used in the second pass.
|
||||||
|
NR == FNR {
|
||||||
|
if (comment_line($0)) {
|
||||||
|
# comment line
|
||||||
|
word = first(substr($0, comment_line($0)), " ")
|
||||||
|
if (is_word(word)) last_occ["#" word] = FNR
|
||||||
|
} else {
|
||||||
|
word = first($0, EQS)
|
||||||
|
if (is_word(word)) last_occ[word] = FNR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# before second pass prepare hashes containing location information to be used
|
||||||
|
# in the second pass.
|
||||||
|
NR > FNR && FNR == 1 {
|
||||||
|
# First we drop the locations of commented-out options if a non-commented
|
||||||
|
# option is available. If a non-commented option is available, we will
|
||||||
|
# append new config options there to have them all at one place.
|
||||||
|
for (k in last_occ)
|
||||||
|
if (k ~ /^\#/ && (substr(k, 2) in last_occ))
|
||||||
|
delete last_occ[k]
|
||||||
|
|
||||||
|
# Reverse the option => line mapping. The line_map allows for easier lookups
|
||||||
|
# in the second pass.
|
||||||
|
for (k in last_occ) line_map[last_occ[k]] = k
|
||||||
|
}
|
||||||
|
|
||||||
|
# second pass, generate and output new config
|
||||||
|
NR > FNR {
|
||||||
|
if (comment_line($0) || empty_line($0)) {
|
||||||
|
# comment or empty line
|
||||||
|
print
|
||||||
|
|
||||||
|
if ((FNR in line_map)) {
|
||||||
|
if (line_map[FNR] ~ /^\#/) {
|
||||||
|
# This line contains a commented config option. If the conf hash
|
||||||
|
# contains options to be set, we output them here because this
|
||||||
|
# option is not used in the current config.
|
||||||
|
k = substr(line_map[FNR], 2)
|
||||||
|
if ((k in conf)) print_confs(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (("INSECURE" in conf) && line_map[FNR] ~ /^\#?SECURE$/) {
|
||||||
|
# INSECURE goes where SECURE comment is.
|
||||||
|
print_confs("INSECURE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
word = first($0, EQS)
|
||||||
|
value = rest($0, EQS)
|
||||||
|
sub(/[ \t]*\#.*$/, "", value) # ignore comments in value
|
||||||
|
|
||||||
|
if ((word in conf) && value == first(conf[word])) {
|
||||||
|
# keep config options we want
|
||||||
|
conf_pop(word)
|
||||||
|
print
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FNR in line_map) && line_map[FNR] == word) {
|
||||||
|
# rest of config options should be here
|
||||||
|
print_confs(word)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
if (e) exit
|
||||||
|
|
||||||
|
# print rest of config options (
|
||||||
|
for (word in conf) print_confs(word)
|
||||||
|
}
|
177
type/__dma/gencode-remote
Executable file
177
type/__dma/gencode-remote
Executable file
|
@ -0,0 +1,177 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
quote() { printf "'%s'" "$(printf '%s' "$*" | sed -e "s/'/'\\\\''/g")"; }
|
||||||
|
drop_awk_comments() { quote "$(sed '/^[[:blank:]]*#.*$/d;/^$/d' "$@")"; }
|
||||||
|
|
||||||
|
CONF_PATH=/etc/dma # set in Makefile
|
||||||
|
|
||||||
|
# Determine mailname
|
||||||
|
if test -f "${__object:?}/parameter/mailname"
|
||||||
|
then
|
||||||
|
mailname=$(cat "${__object:?}/parameter/mailname")
|
||||||
|
else
|
||||||
|
case $(cat "${__global:?}/explorer/os")
|
||||||
|
in
|
||||||
|
(debian|devuan|ubuntu)
|
||||||
|
# On Debian-like systems use /etc/mailname unless --mailname is used
|
||||||
|
mailname='/etc/mailname'
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
mailname=${__target_fqdn:?}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Generate "should" values for config
|
||||||
|
conf_should=$(
|
||||||
|
if test -s "${__object:?}/parameter/smarthost"
|
||||||
|
then
|
||||||
|
printf 'SMARTHOST %s\n' "$(cat "${__object:?}/parameter/smarthost")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'MAILNAME %s\n' "${mailname}"
|
||||||
|
|
||||||
|
if test -s "${__object:?}/explorer/auth_conf"
|
||||||
|
then
|
||||||
|
printf "AUTHPATH %s\n" "$(cat "${__object:?}/explorer/auth_conf")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $(cat "${__object:?}/parameter/security")
|
||||||
|
in
|
||||||
|
(ssl|tls)
|
||||||
|
default_smtp_port=465
|
||||||
|
echo 'SECURETRANSFER'
|
||||||
|
;;
|
||||||
|
(starttls)
|
||||||
|
default_smtp_port=587
|
||||||
|
echo 'SECURETRANSFER'
|
||||||
|
echo 'STARTTLS'
|
||||||
|
;;
|
||||||
|
(opportunistic)
|
||||||
|
default_smtp_port=25
|
||||||
|
echo 'SECURETRANSFER'
|
||||||
|
echo 'STARTTLS'
|
||||||
|
echo 'OPPORTUNISTIC_TLS'
|
||||||
|
;;
|
||||||
|
(insecure)
|
||||||
|
default_smtp_port=25
|
||||||
|
echo 'INSECURE'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -s "${__object:?}/parameter/port"
|
||||||
|
then
|
||||||
|
printf 'PORT %u\n' "$(cat "${__object:?}/parameter/port")"
|
||||||
|
elif test "${default_smtp_port}" -ne 25 # DMA uses port 25 by default
|
||||||
|
then
|
||||||
|
printf 'PORT %u\n' "${default_smtp_port}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f "${__object:?}/parameter/masquerade"
|
||||||
|
then
|
||||||
|
while read -r line
|
||||||
|
do
|
||||||
|
printf 'MASQUERADE %s\n' "${line}"
|
||||||
|
done <"${__object:?}/parameter/masquerade"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f "${__object:?}/parameter/defer"
|
||||||
|
then
|
||||||
|
echo 'DEFER'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f "${__object:?}/parameter/fullbounce"
|
||||||
|
then
|
||||||
|
echo 'FULLBOUNCE'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f "${__object:?}/parameter/nullclient"
|
||||||
|
then
|
||||||
|
test -s "${__object:?}/parameter/smarthost" || {
|
||||||
|
echo '--nullclient requires a --smarthost to be defined' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'NULLCLIENT'
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
# Sort conf_should to compare against "conf_is"
|
||||||
|
conf_should=$(echo "${conf_should}" | sort -s -k 1,1)
|
||||||
|
|
||||||
|
config_updated=false
|
||||||
|
if ! echo "${conf_should}" | cmp -s "${__object:?}/explorer/conf" -
|
||||||
|
then
|
||||||
|
# config needs to be updated
|
||||||
|
dma_conf="${CONF_PATH:?}/dma.conf"
|
||||||
|
|
||||||
|
# The following AWK script will output the new config file to be stored on
|
||||||
|
# disk. To do so it reads the current dma.conf file and the config options
|
||||||
|
# that should be set (from stdin).
|
||||||
|
# Note that the path to the current dma.conf is passed to AWK twice, because
|
||||||
|
# the new file cannot be generated in one pass.
|
||||||
|
|
||||||
|
# The logic tries to place options at a sensible location, that is:
|
||||||
|
# a) if the option is already used in the config file:
|
||||||
|
# group all similar options (e.g. MASQUERADE) at one place in the order
|
||||||
|
# they are listed in stdin.
|
||||||
|
# b) if it is a new option and a "default comment" (e.g. "#PORT 25") exists:
|
||||||
|
# place options grouped directly after the comment (the comment is left
|
||||||
|
# alone)
|
||||||
|
# c) otherwise:
|
||||||
|
# options are grouped by word (the first word in the line) and appended
|
||||||
|
# at the end of the file.
|
||||||
|
|
||||||
|
cat <<-CODE
|
||||||
|
awk $(drop_awk_comments "${__type:?}/files/update_dma_conf.awk") $(quote "${dma_conf}") <<'EOF' >$(quote "${dma_conf}.tmp") \
|
||||||
|
&& cat $(quote "${dma_conf}.tmp") >$(quote "${dma_conf}")
|
||||||
|
${conf_should}
|
||||||
|
EOF
|
||||||
|
rm $(quote "${dma_conf}.tmp")
|
||||||
|
CODE
|
||||||
|
|
||||||
|
config_updated=true
|
||||||
|
echo 'config updated' >>"${__messages_out:?}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Send a test email if enabled and necessary (=configuration changed)
|
||||||
|
if test -f "${__object:?}/parameter/send-test-mail"
|
||||||
|
then
|
||||||
|
if grep -q '^__mail_alias/root:' "${__messages_in:?}" \
|
||||||
|
|| grep -q '^__dma_auth/' "${__messages_in:?}" \
|
||||||
|
|| ${config_updated}
|
||||||
|
then
|
||||||
|
cat <<-CODE
|
||||||
|
sendmail root <<'EOF'
|
||||||
|
Subject: [cdist] Test mail from '${__target_fqdn:?}'
|
||||||
|
|
||||||
|
Hi,
|
||||||
|
|
||||||
|
you can ignore this message.
|
||||||
|
Its sole purpose is to notify you that root mail on ${__target_fqdn:?}
|
||||||
|
will be redirected to you.
|
||||||
|
|
||||||
|
Enjoy!
|
||||||
|
EOF
|
||||||
|
CODE
|
||||||
|
fi
|
||||||
|
fi
|
112
type/__dma/man.rst
Normal file
112
type/__dma/man.rst
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
cdist-type__dma(7)
|
||||||
|
============================
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
cdist-type__dma - Setup the DragonFly Mail Agent as the MTA.
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
This (singleton) type uses DMA, a small Mail Transport Agent (MTA), to accept
|
||||||
|
mails from locally installed Mail User Agents (MUA) and either deliver the mails
|
||||||
|
to a remote smart host for delivery or communicate with remote SMTP servers
|
||||||
|
directly.
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRED PARAMETERS
|
||||||
|
-------------------
|
||||||
|
None.
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN PARAMETERS
|
||||||
|
------------------
|
||||||
|
defer
|
||||||
|
If enabled, mail will not be sent immediately, but stored in a queue.
|
||||||
|
To flush the queue and send the mails, ```dma -q`` has to be run
|
||||||
|
periodically (e.g. using a cron job.)
|
||||||
|
This type does not manage such a cron job, but some operating systems ship
|
||||||
|
such a cron job with the package.
|
||||||
|
fullbounce
|
||||||
|
Enable if bounce messages should include the complete original message,
|
||||||
|
not just the headers.
|
||||||
|
nullclient
|
||||||
|
Enable to bypass aliases and local delivery, and instead forward all mails
|
||||||
|
to the defined ``--smarthost``.
|
||||||
|
send-test-mail
|
||||||
|
If set, this type will send a test email to root after setup, to check if
|
||||||
|
the configured settings work.
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONAL PARAMETERS
|
||||||
|
-------------------
|
||||||
|
mailname
|
||||||
|
If present, this will be the hostname used to identify this host and the
|
||||||
|
remote part of the sender addresses.
|
||||||
|
If not defined, it defaults to ``/etc/mailname`` on Debian derivatives and
|
||||||
|
to ``__target_fqdn`` otherwise.
|
||||||
|
See `dma(8)` for more information.
|
||||||
|
|
||||||
|
Note: on Debian derivatives the ``/etc/mailname`` file should be updated
|
||||||
|
instead of using this parameter.
|
||||||
|
masquerade
|
||||||
|
Masquerade the envelope-from addresses with this address/hostname.
|
||||||
|
Use this setting if mails are not accepted by destination mail servers
|
||||||
|
because your sender domain is invalid.
|
||||||
|
This option can be used multiple times.
|
||||||
|
For more information see the `dma(8)` man page.
|
||||||
|
port
|
||||||
|
The port on which to deliver email.
|
||||||
|
If not provided, a sensible default port will be used based on the
|
||||||
|
``--security`` argument.
|
||||||
|
security
|
||||||
|
Configures whether and how DMA should use secure connections.
|
||||||
|
|
||||||
|
ssl/tls
|
||||||
|
Enable TLS/SSL secured transfer.
|
||||||
|
starttls
|
||||||
|
Use STARTTLS to establish a secure connection.
|
||||||
|
opportunistic (default)
|
||||||
|
Will try to establish a secure connection using STARTTLS, but allow
|
||||||
|
unencrypted transfer if STARTTLS fails.
|
||||||
|
Most useful when dma is used without a smarthost, delivering remote
|
||||||
|
messages directly to the outside mail exchangers.
|
||||||
|
insecure
|
||||||
|
allow plain text SMTP login over an insecure connection.
|
||||||
|
Should really *not* be used anymore!
|
||||||
|
smarthost
|
||||||
|
The mail server used to send email.
|
||||||
|
It must be configured to act as a relay for the host being configured by
|
||||||
|
this type so that mail can be sent to users non-local to the smarthost.
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
# Install DMA and use the smarthost mx1.domain.tld to send mail.
|
||||||
|
__dma --smarthost mx1.domain.tld --send-test-mail
|
||||||
|
|
||||||
|
# Install DMA in a default configuration.
|
||||||
|
__dma
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
- `DragonFly Mail Agent <https://github.com/corecode/dma>`_
|
||||||
|
- `DragonFly Handbook MTA <https://www.dragonflybsd.org/handbook/mta/>`_
|
||||||
|
|
||||||
|
|
||||||
|
AUTHORS
|
||||||
|
-------
|
||||||
|
Evilham <contact@evilham.com>
|
||||||
|
Dennis Camera <dennis.camera@ssrq-sds-fds.ch>
|
||||||
|
|
||||||
|
|
||||||
|
COPYING
|
||||||
|
-------
|
||||||
|
Copyright \(C) 2020 Evilham and Dennis Camera. 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.
|
66
type/__dma/manifest
Executable file
66
type/__dma/manifest
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
os=$(cat "${__global:?}/explorer/os")
|
||||||
|
|
||||||
|
# Install DMA
|
||||||
|
case ${os}
|
||||||
|
in
|
||||||
|
(alpine)
|
||||||
|
__package dma --state present
|
||||||
|
export require='__package/dma'
|
||||||
|
;;
|
||||||
|
(debian|devuan|ubuntu)
|
||||||
|
__package dma --state present
|
||||||
|
export require='__package/dma'
|
||||||
|
;;
|
||||||
|
(freebsd)
|
||||||
|
# Stop sendmail if necessary
|
||||||
|
__process 'sendmail' --name 'sendmail.*' --state absent \
|
||||||
|
--stop '/etc/rc.d/sendmail onestop'
|
||||||
|
|
||||||
|
# ... and disable it
|
||||||
|
__key_value 'rcconf-sendmail-enable' --file '/etc/rc.conf' \
|
||||||
|
--key 'sendmail_enable' --delimiter '=' --value '"NONE"' \
|
||||||
|
--exact_delimiter
|
||||||
|
|
||||||
|
# Setup mailwrapper accordingly
|
||||||
|
__file '/etc/mail/mailer.conf' --mode 0644 --source - <<-'EOF'
|
||||||
|
#
|
||||||
|
# Execute the "real" sendmail program, named /usr/libexec/sendmail/sendmail
|
||||||
|
#
|
||||||
|
sendmail /usr/libexec/dma
|
||||||
|
send-mail /usr/libexec/dma
|
||||||
|
mailq /usr/libexec/dma
|
||||||
|
newaliases /usr/libexec/dma
|
||||||
|
rmail /usr/libexec/dma
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
cat <<EOF >&2
|
||||||
|
Your OS (${os}) is not supported yet.
|
||||||
|
|
||||||
|
Maybe adding support is as simple as adapting the packages or allowing it,
|
||||||
|
we highly encourage you to open a PR with the necessary changes.
|
||||||
|
See: https://code.ungleich.ch/ungleich-public/cdist-contrib/
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
4
type/__dma/parameter/boolean
Normal file
4
type/__dma/parameter/boolean
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
defer
|
||||||
|
fullbounce
|
||||||
|
nullclient
|
||||||
|
send-test-mail
|
1
type/__dma/parameter/default/security
Normal file
1
type/__dma/parameter/default/security
Normal file
|
@ -0,0 +1 @@
|
||||||
|
opportunistic
|
4
type/__dma/parameter/optional
Normal file
4
type/__dma/parameter/optional
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
mailname
|
||||||
|
port
|
||||||
|
security
|
||||||
|
smarthost
|
1
type/__dma/parameter/optional_multiple
Normal file
1
type/__dma/parameter/optional_multiple
Normal file
|
@ -0,0 +1 @@
|
||||||
|
masquerade
|
0
type/__dma/singleton
Normal file
0
type/__dma/singleton
Normal file
1
type/__dma_auth/explorer/auth_conf
Symbolic link
1
type/__dma_auth/explorer/auth_conf
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../__dma/explorer/auth_conf
|
91
type/__dma_auth/explorer/state
Executable file
91
type/__dma_auth/explorer/state
Executable file
|
@ -0,0 +1,91 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# This explorer looks for a line matching the server parameter
|
||||||
|
# in dma's auth.conf and reports:
|
||||||
|
# present: a line matching login + host + password exists
|
||||||
|
# absent: no line matching login + host exists
|
||||||
|
# different_login: a line exists but with a different login user
|
||||||
|
# different_password: a line exists but with a different password
|
||||||
|
# multiple: multiple lines matching host exist (should not happen)
|
||||||
|
|
||||||
|
auth_conf=$("${__type_explorer:?}/auth_conf")
|
||||||
|
test -r "${auth_conf}" || exit 0
|
||||||
|
|
||||||
|
awk -F'\n' '
|
||||||
|
function getvalue(path) {
|
||||||
|
# Reads the first line of the file located at path and returns it.
|
||||||
|
getline < path
|
||||||
|
close(path)
|
||||||
|
return $0
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
DP = "[: \t]" # copied from dma/conf.c
|
||||||
|
|
||||||
|
parameter_dir = ENVIRON["__object"] "/parameter/"
|
||||||
|
|
||||||
|
# Read the parameters of this object
|
||||||
|
host_param = ENVIRON["__object_id"]
|
||||||
|
login_param = getvalue(parameter_dir "login")
|
||||||
|
passwd_param = getvalue(parameter_dir "password")
|
||||||
|
|
||||||
|
state = "absent"
|
||||||
|
}
|
||||||
|
|
||||||
|
/^#/ || /^$/ {
|
||||||
|
# skip comments and empty lines
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# parse line
|
||||||
|
|
||||||
|
login = substr($0, 1, index($0, "|") - 1)
|
||||||
|
if (!login) { login = $0 } # if no "|" found
|
||||||
|
|
||||||
|
host = substr($0, length(login) + 2)
|
||||||
|
|
||||||
|
if (match(host, DP)) {
|
||||||
|
passwd = substr(host, RSTART + 1)
|
||||||
|
host = substr(host, 1, RSTART - 1)
|
||||||
|
} else {
|
||||||
|
passwd = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
host == host_param {
|
||||||
|
# a match…
|
||||||
|
if (state == "absent") {
|
||||||
|
if (login != login_param)
|
||||||
|
state = "different_login"
|
||||||
|
else if (passwd != passwd_param)
|
||||||
|
state = "different_password"
|
||||||
|
else
|
||||||
|
state = "present"
|
||||||
|
} else {
|
||||||
|
# report "multiple" to that the type can remove the duplicates.
|
||||||
|
state = "multiple"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print state
|
||||||
|
}
|
||||||
|
' "${auth_conf}"
|
93
type/__dma_auth/files/update_dma_auth.awk
Normal file
93
type/__dma_auth/files/update_dma_auth.awk
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#!/usr/bin/awk -f
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
function getvalue(path) {
|
||||||
|
# Reads the first line of the file located at path and returns it.
|
||||||
|
getline < path
|
||||||
|
close(path)
|
||||||
|
return $0
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_should() {
|
||||||
|
printf "%s|%s:%s\n", login_param, host_param, passwd_param
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
FS = "\n"
|
||||||
|
DP = "[: \t]" # copied from dma/conf.c
|
||||||
|
|
||||||
|
parameter_dir = ENVIRON["__object"] "/parameter/"
|
||||||
|
|
||||||
|
mode = (getvalue(parameter_dir "state") != "absent")
|
||||||
|
|
||||||
|
host_param = ENVIRON["__object_id"]
|
||||||
|
login_param = getvalue(parameter_dir "login")
|
||||||
|
passwd_param = getvalue(parameter_dir "password")
|
||||||
|
}
|
||||||
|
|
||||||
|
# skip comments and empty lines
|
||||||
|
/^#/ || /^$/ {
|
||||||
|
print
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# parse line (like dma/conf.c would)
|
||||||
|
|
||||||
|
login = substr($0, 1, index($0, "|") - 1)
|
||||||
|
if (!login) { login = $0 } # if no "|" found
|
||||||
|
|
||||||
|
host = substr($0, length(login) + 2)
|
||||||
|
|
||||||
|
if (match(host, DP)) {
|
||||||
|
passwd = substr(host, RSTART + 1)
|
||||||
|
host = substr(host, 1, RSTART - 1)
|
||||||
|
} else {
|
||||||
|
passwd = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
host == host_param {
|
||||||
|
if (mode) {
|
||||||
|
# state_should == present
|
||||||
|
if (!written) {
|
||||||
|
# replace first line if host matches (but only if no line has
|
||||||
|
# been written already -> no duplicates)
|
||||||
|
print_should()
|
||||||
|
written = 1
|
||||||
|
}
|
||||||
|
next
|
||||||
|
} else {
|
||||||
|
# state_should == absent
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# leave other lines alone
|
||||||
|
{
|
||||||
|
print
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
if (mode && !written) {
|
||||||
|
# append line if no match to replace was found
|
||||||
|
print_should()
|
||||||
|
}
|
||||||
|
}
|
72
type/__dma_auth/gencode-remote
Executable file
72
type/__dma_auth/gencode-remote
Executable file
|
@ -0,0 +1,72 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
quote() { printf "'%s'" "$(printf '%s' "$*" | sed -e "s/'/'\\\\''/g")"; }
|
||||||
|
drop_awk_comments() { quote "$(sed '/^[[:blank:]]*#.*$/d;/^$/d' "$@")"; }
|
||||||
|
|
||||||
|
state_is=$(cat "${__object:?}/explorer/state")
|
||||||
|
state_should=$(cat "${__object:?}/parameter/state")
|
||||||
|
|
||||||
|
server=${__object_id:?}
|
||||||
|
login=$(cat "${__object:?}/parameter/login")
|
||||||
|
|
||||||
|
|
||||||
|
auth_conf=$(cat "${__object:?}/explorer/auth_conf")
|
||||||
|
test -n "${auth_conf}" || {
|
||||||
|
echo 'Cannot determine path of dma auth.conf' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if test "${state_is}" = "${state_should}"
|
||||||
|
then
|
||||||
|
# state is as it should
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
case ${state_should}
|
||||||
|
in
|
||||||
|
(present)
|
||||||
|
test -n "${login}" || { echo '--login must be non-empty' >&2; exit 1; }
|
||||||
|
|
||||||
|
if test "${state_is}" = 'absent'
|
||||||
|
then
|
||||||
|
printf 'add authuser %s on %s\n' "${login}" "${server}" >>"${__messages_out:?}"
|
||||||
|
else
|
||||||
|
printf 'set authuser %s on %s\n' "${login}" "${server}" >>"${__messages_out:?}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
(absent)
|
||||||
|
printf 'delete authuser %s on %s\n' "${login}" "${server}" >>"${__messages_out:?}"
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
printf 'Invalid --state: %s.\n' "${state_should}" >&2
|
||||||
|
printf 'Acceptable values are: present, absent.\n' >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
test -f $(quote "${auth_conf}") || touch $(quote "${auth_conf}")
|
||||||
|
|
||||||
|
awk $(drop_awk_comments "${__type:?}/files/update_dma_auth.awk") <$(quote "${auth_conf}") >$(quote "${auth_conf}.tmp") \
|
||||||
|
&& cat $(quote "${auth_conf}.tmp") >$(quote "${auth_conf}")
|
||||||
|
rm -f $(quote "${auth_conf}.tmp")
|
||||||
|
EOF
|
66
type/__dma_auth/man.rst
Normal file
66
type/__dma_auth/man.rst
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
cdist-type__dma_auth(7)
|
||||||
|
=======================
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
cdist-type__dma_auth - Configure SMTP logins for the DragonFly Mail Agent MTA.
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
This cdist type allows you to set up credentials to log in to remote SMTP
|
||||||
|
servers.
|
||||||
|
|
||||||
|
NB: dma currently (v0.13) does not differentiate between users on a host.
|
||||||
|
It will use whatever user it finds in the ``auth.conf`` first.
|
||||||
|
Thus, this type will use the ``__object_id`` as the host specifier.
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRED PARAMETERS
|
||||||
|
-------------------
|
||||||
|
login
|
||||||
|
The user's LOGIN name on the SMTP server.
|
||||||
|
password
|
||||||
|
The user's password (in plain text.)
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONAL PARAMETERS
|
||||||
|
-------------------
|
||||||
|
state
|
||||||
|
Either ``present`` or ``absent``. Defaults to ``present``.
|
||||||
|
|
||||||
|
BOOLEAN PARAMETERS
|
||||||
|
------------------
|
||||||
|
None.
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
# Set the password for smarthost
|
||||||
|
__dma_auth smarthost.example.com --login joe --password hunter2
|
||||||
|
|
||||||
|
# Set credentials for user at an external provider
|
||||||
|
__dma_auth mail.provider.com --login paul@example.com --password letmein
|
||||||
|
|
||||||
|
# Delete credentials for example.com (for all users)
|
||||||
|
__dma_auth example.com --login '' --password '' --state absent
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
:strong:`cdist-type__dma`\ (7), :strong:`dma`\ (8)
|
||||||
|
|
||||||
|
|
||||||
|
AUTHORS
|
||||||
|
-------
|
||||||
|
Dennis Camera <dennis.camera@ssrq-sds-fds.ch>
|
||||||
|
|
||||||
|
|
||||||
|
COPYING
|
||||||
|
-------
|
||||||
|
Copyright \(C) 2020 Dennis Camera. 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.
|
0
type/__dma_auth/nonparallel
Normal file
0
type/__dma_auth/nonparallel
Normal file
1
type/__dma_auth/parameter/default/state
Normal file
1
type/__dma_auth/parameter/default/state
Normal file
|
@ -0,0 +1 @@
|
||||||
|
present
|
1
type/__dma_auth/parameter/optional
Normal file
1
type/__dma_auth/parameter/optional
Normal file
|
@ -0,0 +1 @@
|
||||||
|
state
|
2
type/__dma_auth/parameter/required
Normal file
2
type/__dma_auth/parameter/required
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
login
|
||||||
|
password
|
73
type/__mail_alias/explorer/aliases
Executable file
73
type/__mail_alias/explorer/aliases
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Find aliases for a given user name and print the aliases (each one on a
|
||||||
|
# separate line)
|
||||||
|
|
||||||
|
aliases_file=$("${__type_explorer:?}/aliases_file")
|
||||||
|
test -r "${aliases_file}" || exit 0
|
||||||
|
|
||||||
|
: "${__object_id:?}" # assert __object_id is set, because it is used in AWK
|
||||||
|
|
||||||
|
awk -F ':[ \t]*' '
|
||||||
|
function print_aliases(aliases, matches) {
|
||||||
|
# prints comma-separated aliases (one per line)
|
||||||
|
split(aliases, matches, /,[ \t]*/)
|
||||||
|
for (i in matches) {
|
||||||
|
gsub(/^[ \t]*|[ \t]*$/, "", matches[i])
|
||||||
|
if (matches[i]) print matches[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/^#/ {
|
||||||
|
# comment line (ignore)
|
||||||
|
select = 0; cont = 0 # comments terminate alias lists and continuations
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# is this line a continuation line?
|
||||||
|
# (the prev. line ended in a backslash or the line starts with whitespace)
|
||||||
|
is_cont = /^[ \t]/ || cont
|
||||||
|
|
||||||
|
# detect if the line is a line to be continued (ends with a backslash)
|
||||||
|
cont = /\\$/
|
||||||
|
|
||||||
|
# if it is, we drop the backslash from the line
|
||||||
|
if (cont) sub(/[ \t]*\\$/, "", $0)
|
||||||
|
}
|
||||||
|
|
||||||
|
is_cont {
|
||||||
|
# if in the alias list of the "target" user, we also print these aliases.
|
||||||
|
if (select) print_aliases($0)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
$1 == ENVIRON["__object_id"] {
|
||||||
|
# "target" user -> print alias list
|
||||||
|
select = 1
|
||||||
|
print_aliases($2)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# other user
|
||||||
|
select = 0
|
||||||
|
}
|
||||||
|
' "${aliases_file}"
|
52
type/__mail_alias/explorer/aliases_file
Executable file
52
type/__mail_alias/explorer/aliases_file
Executable file
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# This explorer finds the aliases file to modify.
|
||||||
|
|
||||||
|
found() { echo "$*"; exit 0; }
|
||||||
|
|
||||||
|
check_file() {
|
||||||
|
if test -f "$1"
|
||||||
|
then
|
||||||
|
found "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case $("${__explorer:?}/os")
|
||||||
|
in
|
||||||
|
(freebsd|openbsd|solaris)
|
||||||
|
check_file /etc/mail/aliases
|
||||||
|
|
||||||
|
# default
|
||||||
|
found /etc/mail/aliases
|
||||||
|
;;
|
||||||
|
(alpine|debian|devuan|ubuntu)
|
||||||
|
check_file /etc/aliases
|
||||||
|
|
||||||
|
# default
|
||||||
|
found /etc/aliases
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
check_file /etc/mail/aliases
|
||||||
|
check_file /etc/aliases
|
||||||
|
|
||||||
|
# default
|
||||||
|
found /etc/aliases
|
||||||
|
;;
|
||||||
|
esac
|
96
type/__mail_alias/files/update_aliases.awk
Normal file
96
type/__mail_alias/files/update_aliases.awk
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
#!/usr/bin/awk -f
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
function getvalue(path, line) {
|
||||||
|
# Reads the first line of the file located at path and returns it.
|
||||||
|
getline line < path
|
||||||
|
close(path)
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
|
function sepafter(f, def, _) {
|
||||||
|
# finds the separator between field $f and $(f+1)
|
||||||
|
_ = substr($0, length($f)+1, index(substr($0, length($f)+1), $(f+1))-1)
|
||||||
|
return _ ? _ : def
|
||||||
|
}
|
||||||
|
|
||||||
|
function write_aliases( line) {
|
||||||
|
if (aliases_written) return
|
||||||
|
|
||||||
|
# print aliases line
|
||||||
|
printf "%s%s", ENVIRON["__object_id"], sepafter(1, ": ")
|
||||||
|
while ((getline line < aliases_should_file) > 0) {
|
||||||
|
if (aliases_written) printf ", "
|
||||||
|
printf "%s", line
|
||||||
|
aliases_written = 1
|
||||||
|
}
|
||||||
|
printf "\n"
|
||||||
|
close(aliases_should_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
FS = ":[ \t]*"
|
||||||
|
|
||||||
|
parameter_dir = ENVIRON["__object"] "/parameter/"
|
||||||
|
|
||||||
|
mode = (getvalue(parameter_dir "state") != "absent")
|
||||||
|
aliases_should_file = (parameter_dir "/alias")
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*\#/ {
|
||||||
|
# comment line (leave alone)
|
||||||
|
select = 0; cont = 0 # comments terminate alias lists and continuations
|
||||||
|
print
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# is this line a continuation line?
|
||||||
|
# (the prev. line ended in a backslash or the line starts with whitespace)
|
||||||
|
is_cont = /^[ \t]/ || cont
|
||||||
|
|
||||||
|
# detect if the line is a line to be continued (ends with a backslash)
|
||||||
|
cont = /\\$/
|
||||||
|
}
|
||||||
|
|
||||||
|
is_cont {
|
||||||
|
# we only print the line if it has not been rewritten (select)
|
||||||
|
if (!select) print
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
$1 == ENVIRON["__object_id"] {
|
||||||
|
# "target" user -> rewrite aliases list
|
||||||
|
select = 1
|
||||||
|
if (mode) write_aliases()
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# other user
|
||||||
|
select = 0
|
||||||
|
print
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
# if the last line was an alias, the separator will be reused (looks better)
|
||||||
|
if (mode && !aliases_written)
|
||||||
|
write_aliases()
|
||||||
|
}
|
87
type/__mail_alias/gencode-remote
Executable file
87
type/__mail_alias/gencode-remote
Executable file
|
@ -0,0 +1,87 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
#
|
||||||
|
# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
quote() { printf "'%s'" "$(printf '%s' "$*" | sed -e "s/'/'\\\\''/g")"; }
|
||||||
|
drop_awk_comments() { quote "$(sed '/^[[:blank:]]*#.*$/d;/^$/d' "$@")"; }
|
||||||
|
|
||||||
|
aliases_file=$(cat "${__object:?}/explorer/aliases_file")
|
||||||
|
|
||||||
|
test -n "${aliases_file}" || {
|
||||||
|
echo 'Could not determine aliases file path.' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
state_should=$(cat "${__object:?}/parameter/state")
|
||||||
|
|
||||||
|
case ${state_should}
|
||||||
|
in
|
||||||
|
(present)
|
||||||
|
if cmp -s "${__object:?}/explorer/aliases" "${__object:?}/parameter/alias"
|
||||||
|
then
|
||||||
|
# all good!
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -s "${__object:?}/parameter/alias" || {
|
||||||
|
printf 'The --alias parameter is required if --state present.\n' >&2
|
||||||
|
printf 'Use --state absent to remove all aliases.\n' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if test -s "${__object:?}/explorer/aliases"
|
||||||
|
then
|
||||||
|
echo "update aliases" >>"${__messages_out:?}"
|
||||||
|
else
|
||||||
|
echo "add aliases" >>"${__messages_out:?}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
(absent)
|
||||||
|
# nothing to do if no aliases found.
|
||||||
|
test -s "${__object:?}/explorer/aliases" || exit 0
|
||||||
|
|
||||||
|
echo "delete aliases" >>"${__messages_out:?}"
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
printf 'Invalid --state: %s.\n' "${state_should}" >&2
|
||||||
|
printf 'Acceptable values are: present, absent.\n' >&2
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
test -f $(quote "${aliases_file}") || touch $(quote "${aliases_file}")
|
||||||
|
|
||||||
|
awk $(drop_awk_comments "${__type:?}/files/update_aliases.awk") <$(quote "${aliases_file}") >$(quote "${aliases_file}.tmp") \
|
||||||
|
|| {
|
||||||
|
rm -f $(quote "${aliases_file}.tmp")
|
||||||
|
echo 'Generating new aliases file failed!' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! cmp -s $(quote "${aliases_file}") $(quote "${aliases_file}.tmp")
|
||||||
|
then
|
||||||
|
# aliases file was modified, replace:
|
||||||
|
cat $(quote "${aliases_file}.tmp") >$(quote "${aliases_file}")
|
||||||
|
|
||||||
|
# then, run newaliases if present ("missing" on Alpine Linux because of typo)
|
||||||
|
command -v newaliases >/dev/null 2>&1 && newaliases || true
|
||||||
|
fi
|
||||||
|
rm -f $(quote "${aliases_file}.tmp")
|
||||||
|
EOF
|
76
type/__mail_alias/man.rst
Normal file
76
type/__mail_alias/man.rst
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
cdist-type__mail_alias(7)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
cdist-type__mail_alias - Manage mail aliases.
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
This cdist type allows you to configure mail aliases (/etc/aliases).
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRED PARAMETERS
|
||||||
|
-------------------
|
||||||
|
None.
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONAL PARAMETERS
|
||||||
|
-------------------
|
||||||
|
state
|
||||||
|
'present' or 'absent', defaults to 'present'
|
||||||
|
alias
|
||||||
|
an alias, i.e. a mail address where mail for the user should be redirected
|
||||||
|
to.
|
||||||
|
This parameter can be specified multiple times to redirect to multiple
|
||||||
|
recipients.
|
||||||
|
If ``--state`` is ``present`` this parameter is required.
|
||||||
|
See `aliases(5)` for the different forms this parameter can take.
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN PARAMETERS
|
||||||
|
------------------
|
||||||
|
None.
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
# Redirect root mail to a "real" email address
|
||||||
|
__mail_alias root --alias admin@example.com
|
||||||
|
|
||||||
|
# Disable redirection of mail for joe
|
||||||
|
__mail_alias joe --state absent
|
||||||
|
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
----
|
||||||
|
- Quoted strings are not parsed by this type. As a result, aliases
|
||||||
|
containing ``,`` (commas) are treated incorrectly (they are treated as
|
||||||
|
separate aliases.)
|
||||||
|
Make sure that email addresses, file names, and pipe commands do not contain
|
||||||
|
commas.
|
||||||
|
- ``:include:`` directives in the aliases file are not evaluated by this type.
|
||||||
|
They are treated like a regular alias, the values of the included file are
|
||||||
|
not expanded.
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
:strong:`aliases`\ (5)
|
||||||
|
|
||||||
|
|
||||||
|
AUTHORS
|
||||||
|
-------
|
||||||
|
Dennis Camera <dennis.camera@ssrq-sds-fds.ch>
|
||||||
|
|
||||||
|
|
||||||
|
COPYING
|
||||||
|
-------
|
||||||
|
Copyright \(C) 2020 Dennis Camera. 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.
|
0
type/__mail_alias/nonparallel
Normal file
0
type/__mail_alias/nonparallel
Normal file
1
type/__mail_alias/parameter/default/state
Normal file
1
type/__mail_alias/parameter/default/state
Normal file
|
@ -0,0 +1 @@
|
||||||
|
present
|
1
type/__mail_alias/parameter/optional
Normal file
1
type/__mail_alias/parameter/optional
Normal file
|
@ -0,0 +1 @@
|
||||||
|
state
|
1
type/__mail_alias/parameter/optional_multiple
Normal file
1
type/__mail_alias/parameter/optional_multiple
Normal file
|
@ -0,0 +1 @@
|
||||||
|
alias
|
Loading…
Reference in a new issue