530
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
postfixLabel="[Postfix]"
|
||||
|
||||
# Generates a self-signed TLS certificate for Postfix if one does not already exist.
|
||||
function cmdPostfixPreparation() {
|
||||
if [[ ! -f "$postfixTlsCrtFile" || ! -f "$postfixTlsKeyFile" ]]; then
|
||||
local crtPath; crtPath=$(dirname "$postfixTlsCrtFile")
|
||||
local tlsCnfFile="$crtPath/openssl.cnf"
|
||||
local cn="${postfixHost:-$postfixDomain}"
|
||||
local sanList="DNS:${cn}"
|
||||
[[ -n "$postfixDomain" ]] && sanList="${sanList},DNS:${postfixDomain}"
|
||||
mkdir -p "$crtPath" || { printDanger "Failed to create folder for certificate"; return 1; }
|
||||
|
||||
cat >"$tlsCnfFile" <<EOF
|
||||
[req]
|
||||
distinguished_name = dn
|
||||
x509_extensions = v3_req
|
||||
prompt = no
|
||||
[dn]
|
||||
CN = ${cn}
|
||||
[v3_req]
|
||||
subjectAltName = ${sanList}
|
||||
keyUsage = digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
EOF
|
||||
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
|
||||
-keyout "$postfixTlsKeyFile" -out "$postfixTlsCrtFile" -config "$tlsCnfFile" \
|
||||
|| { printDanger "TLS gen failed"; return 1; }
|
||||
fi
|
||||
}
|
||||
|
||||
# Renders the Postfix Kubernetes YAML manifest via Helm.
|
||||
function cmdPostfixYamlRender() {
|
||||
printInfo "$postfixLabel Render YAML | Helm"
|
||||
|
||||
local templateFile="templates/$postfixKube.yaml"
|
||||
if [[ ! -f "$appAssetsPath/k3s/$templateFile" ]]; then
|
||||
printDanger "$postfixLabel Template YAML : File not found | $appAssetsPath/k3s/$templateFile"
|
||||
return 1
|
||||
fi
|
||||
printInfo "$postfixLabel Template YAML : $appAssetsPath/k3s/$templateFile"
|
||||
|
||||
local val postfixTlsCrtB64 postfixTlsKeyB64
|
||||
val=$(base64 -w0 "$postfixTlsCrtFile") || { printDanger "Base64 gen failed"; return 1; }
|
||||
postfixTlsCrtB64=$(sed 's/[&\\]/\\&/g' <<<"$val") || { printDanger "Base64 gen failed"; return 1; }
|
||||
val=$(base64 -w0 "$postfixTlsKeyFile") || { printDanger "Base64 gen failed"; return 1; }
|
||||
postfixTlsKeyB64=$(sed 's/[&\\]/\\&/g' <<<"$val") || { printDanger "Base64 gen failed"; return 1; }
|
||||
|
||||
local varsFile
|
||||
varsFile=$(mktemp "/tmp/$postfixKube.vars.XXXXXX.yaml") || return 1
|
||||
printInfo "$postfixLabel Variables : $varsFile"
|
||||
trap 'rm -f -- "$varsFile"' RETURN
|
||||
cat > "$varsFile" <<EOF
|
||||
postfixHelm: true
|
||||
namespace: $k3sNamespace
|
||||
postfix: $postfixKube
|
||||
postfixPath: $postfixPath
|
||||
postfixTlsCrtB64: $postfixTlsCrtB64
|
||||
postfixTlsKeyB64: $postfixTlsKeyB64
|
||||
postfixHost: $postfixHost
|
||||
postfixPostmaster: $postfixPostmaster
|
||||
postfixDefaultRealm: $postfixDefaultRealm
|
||||
postfixConfigPath: $postfixConfigPath
|
||||
postfixDkimPath: $postfixDkimPath
|
||||
postfixDkimSelector: $postfixDkimSelector
|
||||
postfixDomainsFile: $postfixDomainsFile
|
||||
postfixAliasesFile: $postfixAliasesFile
|
||||
postfixSendersFile: $postfixSendersFile
|
||||
EOF
|
||||
|
||||
printInfo "$postfixLabel Render file : $postfixYaml"
|
||||
mkdir -p -- "$(dirname -- "$postfixYaml")" || return 1
|
||||
fileBackup "$postfixYaml"
|
||||
helm template stack "$appAssetsPath/k3s" -f "$varsFile" --show-only "$templateFile" > "$postfixYaml" \
|
||||
|| { printDanger "$postfixLabel Render failed"; return 1; }
|
||||
|
||||
printSuccess "$postfixLabel Render completed"
|
||||
}
|
||||
|
||||
# Initializes Postfix after install: generates DKIM for postfixHost and sets sasldb2 ownership.
|
||||
function cmdPostfixInit() {
|
||||
postfixDkimAdd "$postfixHost" || return 1
|
||||
local error
|
||||
if ! runError error postfixExec chown postfix:postfix /config/sasldb2; then
|
||||
printDanger "$postfixLabel | $error"
|
||||
fi
|
||||
}
|
||||
|
||||
# Installs Postfix into Kubernetes.
|
||||
function cmdPostfixInstall() {
|
||||
cmdPostfixPreparation || return 1
|
||||
cmdPostfixYamlRender || return 1
|
||||
cmdK3sYamlApplyEx "$postfixYaml" || return 1
|
||||
}
|
||||
|
||||
# Uninstalls Postfix Kubernetes resources.
|
||||
function cmdPostfixUninstall() {
|
||||
"$k3sCmd" kubectl delete -f "$postfixYaml"
|
||||
}
|
||||
|
||||
# Prints the Postfix mail version.
|
||||
function cmdPostfixInfo() {
|
||||
local output error podList ver pid
|
||||
|
||||
if ! run podList error k3sPodListStatus "$postfixKube"; then
|
||||
printDanger "Get pods: $error"
|
||||
elif [[ -z "$podList" ]]; then
|
||||
printDanger "Pods not found"
|
||||
else
|
||||
while IFS='|' read -r pod phase; do
|
||||
printSection "$pod"
|
||||
|
||||
if [[ "$phase" != "Running" ]]; then
|
||||
printDot 60 "Phase" "$fontRed$phase$fontReset"
|
||||
else
|
||||
printDot 60 "Phase" "$fontGreen$phase$fontReset"
|
||||
|
||||
if ! run output error postfixPodExec "$pod" postfix status; then
|
||||
printDot 60 "Postfix status" "$fontRed$labelFail$fontReset"
|
||||
printDanger "$error"
|
||||
else
|
||||
output="${output:-$error}"
|
||||
if [[ $output == *"is running"* ]]; then
|
||||
pid=${output##*PID: }
|
||||
pid=${pid%%[^0-9]*}
|
||||
printDot 60 "Postfix status" "$labelRunning"
|
||||
printDot 60 "pid" "$pid"
|
||||
else
|
||||
printDot 60 "Postfix status" "$fontRed$output$fontReset"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! run output error postfixPodExec "$pod" postconf mail_version; then
|
||||
printDot 60 "Postfix mail version" "$fontRed$labelFail$fontReset"
|
||||
printDanger "$error"
|
||||
else
|
||||
ver=$(printf '%s' "$output" | cut -d '=' -f2 | tr -d '\r\n')
|
||||
printDot 60 "Postfix mail version" "$ver"
|
||||
fi
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$podList")
|
||||
fi
|
||||
|
||||
printRow
|
||||
}
|
||||
|
||||
# Sets a virtual alias forward-to address for a domain and saves it to site config.
|
||||
# $1 (domain): site domain name.
|
||||
# $2 (mail): forward-to email address.
|
||||
function cmdPostfixVirtualAliasSetEx() {
|
||||
local domain="$1"
|
||||
[[ -n "$domain" ]] || { printDanger "$postfixLabel Domain not specified"; return 1; }
|
||||
local mail="$2"
|
||||
[[ -n "$mail" ]] || { printDanger "$postfixLabel Mail not specified"; return 1; }
|
||||
|
||||
local domainList output error
|
||||
if ! run domainList error postfixDomainList; then
|
||||
printDanger "$postfixLabel postfixDomainList: $error"
|
||||
return 1
|
||||
elif ! listContains "$domain" "$domainList"; then
|
||||
printDanger "$postfixLabel Domain not found in postfixDomainList"
|
||||
return 1
|
||||
elif ! run output error siteConfigSet "$domain" "postfixForwardTo" "$mail"; then
|
||||
printDanger "$postfixLabel siteConfigSet: $error"
|
||||
elif ! run output error postfixVirtualAliasSet "@$domain" "$mail"; then
|
||||
printDanger "$postfixLabel postfixVirtualAliasSet: $error"
|
||||
fi
|
||||
}
|
||||
|
||||
# Checks MTA host DNS records (A, SPF, PTR, DKIM) against configured values.
|
||||
function cmdPostfixMtaDnsCheck() {
|
||||
local label output error text
|
||||
|
||||
label="$postfixLabel A record: $postfixHost"
|
||||
if ! run output error dig +short A "$postfixHost" "$postfixResolver"; then
|
||||
printDanger "$label"
|
||||
else
|
||||
text=$(printf '%s' "$output" | paste -sd, - | sed 's/,/ \/ /g')
|
||||
if grep -Fxq -- "$postfixIp" <<<"$output"; then
|
||||
printSuccess "$label | $text"
|
||||
else
|
||||
printWarning "$label | $text"
|
||||
fi
|
||||
fi
|
||||
|
||||
label="$postfixLabel SPF record: $postfixHost"
|
||||
if ! run output error dig +short TXT "$postfixHost" "$postfixResolver"; then
|
||||
printDanger "$label"
|
||||
elif grep -Eq '^"?v=spf1([[:space:]]|")' <<<"$output"; then
|
||||
printSuccess "$label | $output"
|
||||
else
|
||||
printWarning "$label | $output"
|
||||
fi
|
||||
|
||||
label="$postfixLabel PTR record: $postfixHost"
|
||||
if ! run output error dig -x "$postfixIp" +short "$postfixResolver"; then
|
||||
printDanger "$label"
|
||||
else
|
||||
text=$(printf '%s' "$output" | paste -sd, - | sed 's/,/ \/ /g')
|
||||
if grep -Fxq -- "$postfixHost." <<<"$output"; then
|
||||
printSuccess "$label | $text"
|
||||
else
|
||||
printWarning "$label | $text"
|
||||
fi
|
||||
fi
|
||||
|
||||
label="$postfixLabel DKIM record: $postfixHost"
|
||||
if ! run output error dig +short TXT "$postfixDkimSelector._domainkey.$postfixHost"; then
|
||||
printDanger "$label | $error"
|
||||
else
|
||||
local dkimDnsNorm dkimFileRaw dkimFileNorm
|
||||
dkimDnsNorm=$(
|
||||
printf '%s\n' "$output" |
|
||||
tr -d '\n' |
|
||||
sed -e 's/"//g' -e 's/[[:space:]]//g' |
|
||||
sed -n 's/.*p=\([^;]*\).*/\1/p'
|
||||
)
|
||||
|
||||
dkimFileRaw=$(postfixDkimGet "$postfixHost")
|
||||
dkimFileNorm=$(
|
||||
printf '%s\n' "$dkimFileRaw" |
|
||||
tr -d '\n' |
|
||||
sed -e 's/[()"]//g' -e 's/[[:space:]]//g' |
|
||||
sed -n 's/.*p=\([^;]*\).*/\1/p'
|
||||
)
|
||||
|
||||
if [[ "$dkimDnsNorm" == "$dkimFileNorm" ]]; then
|
||||
printSuccess "$label | OK"
|
||||
else
|
||||
printWarning "$label | DNS : $dkimDnsNorm"
|
||||
printWarning "$label | FILE: $dkimFileNorm"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Prints domain/alias/sender/SASL lists; accepts domain/alias/senders/sasl as filter.
|
||||
# [$1] (filter): domain|alias|senders|sasl; omit to print all.
|
||||
function cmdPostfixList() {
|
||||
case "$1" in
|
||||
'domain')
|
||||
postfixDomainList
|
||||
;;
|
||||
'alias')
|
||||
postfixAliasList
|
||||
;;
|
||||
'senders')
|
||||
postfixSendersList
|
||||
;;
|
||||
'sasl')
|
||||
postfixSaslUserList
|
||||
;;
|
||||
*)
|
||||
printInfo "$postfixLabel Domains"
|
||||
postfixDomainList
|
||||
|
||||
printInfo "$postfixLabel Aliases"
|
||||
postfixAliasList
|
||||
|
||||
printInfo "$postfixLabel Senders"
|
||||
postfixSendersList
|
||||
|
||||
printInfo "$postfixLabel SASL users"
|
||||
postfixSaslUserList
|
||||
;;
|
||||
esac
|
||||
}
|
||||
Reference in New Issue
Block a user