commit 0eadac325a4704775f1fe3ccdf0964de86beb735 Author: Dominik Meyer Date: Mon Jan 27 18:19:49 2025 +0100 chore: initial commit diff --git a/.drone.jsonnet b/.drone.jsonnet new file mode 100644 index 0000000..20d80a1 --- /dev/null +++ b/.drone.jsonnet @@ -0,0 +1,221 @@ +local architectures = ["amd64","arm64"]; + +local image_name = "qpsmtpd"; + +local github_repo_name = "container-qpsmtpd"; +local github_desc = "Container for runnung qpsmtpd"; +local url = "https://gitea.federationhq.de/Container/qpsmtpd" + +local version_1_0_0 = +{ + tag: "1.0.0", + additional_tags: ["1.0","1"], + dir: ".", + +}; + + +local versions = [version_1_0_0]; + + +local build_steps(versions,arch) = [ + { + name: "Build " + version.tag, + image: "quay.io/buildah/stable", + privileged: true, + volumes: + [ + { + name: "fedhq-ca-crt", + path: "/etc/ssl/certs2/" + + } + ], + commands: [ + "scripts/setupEnvironment.sh", + "cd " + version.dir + ";" + 'buildah bud --network host -t "registry.cloud.federationhq.de/' + image_name + ':' +version.tag + "-" + arch + '" --arch ' + arch, + 'buildah push --all registry.cloud.federationhq.de/'+ image_name+':'+version.tag + "-" + arch + + ] + } + for version in versions +]; + +local build_pipelines(architectures) = [ + { + kind: "pipeline", + type: "kubernetes", + name: "build-"+arch, + platform: { + arch: arch + }, + volumes: + [ + { + name: "fedhq-ca-crt", + config_map: + { + name: "fedhq-ca-crt", + default_mode: 420, + optional: false + }, + + } + ], + node_selector: + { + 'kubernetes.io/arch': arch, + 'federationhq.de/compute': true + }, + steps: build_steps(versions, arch), + } + for arch in architectures +]; + + + +local push_pipelines(versions, architectures) = [ + { + kind: "pipeline", + type: "kubernetes", + name: "push-"+version.tag, + platform: { + arch: "amd64" + }, + volumes: + [ + { + name: "fedhq-ca-crt", + config_map: + { + name: "fedhq-ca-crt", + default_mode: 420, + optional: false + }, + + } + ], + node_selector: + { + 'kubernetes.io/arch': "amd64", + 'federationhq.de/compute': true + }, + depends_on: [ + "build-"+arch + for arch in architectures + ], + steps: + [ + { + name: "Push " + version.tag, + image: "quay.io/buildah/stable", + privileged: true, + environment: + { + USERNAME: + { + from_secret: "username" + }, + PASSWORD: + { + from_secret: "password" + } + }, + volumes: + [ + { + name: "fedhq-ca-crt", + path: "/etc/ssl/certs2/" + + } + ], + commands: + [ + "scripts/setupEnvironment.sh", + "buildah manifest create " + image_name + ":"+version.tag, + ] + + + [ + "buildah manifest add redmine:" + version.tag + " registry.cloud.federationhq.de/" + image_name + ":"+version.tag + "-" + arch + for arch in architectures + ] + + + [ + "buildah manifest push --all redmine:"+version.tag + " docker://registry.cloud.federationhq.de/" + image_name +":"+tag + for tag in [version.tag]+version.additional_tags + ] + + + [ + "buildah login -u $${USERNAME} -p $${PASSWORD} registry.hub.docker.com", + ] + + + [ + "buildah manifest push --all " + image_name + ":"+version.tag + " docker://registry.hub.docker.com/byterazor/" + image_name +":"+tag + for tag in [version.tag]+version.additional_tags + ] + } + ] + } + for version in versions +]; + +local push_github = { + kind: "pipeline", + type: "kubernetes", + name: "mirror-to-github", + node_selector: { + "kubernetes.io/arch": "amd64", + "federationhq.de/location": "Blumendorf", + "federationhq.de/compute": true + }, + steps: [ + { + name: "github-mirror", + image: "registry.cloud.federationhq.de/drone-github-mirror:latest", + pull: "always", + settings: { + GH_TOKEN: { + from_secret: "GH_TOKEN" + }, + GH_REPO: "byterazor/" + github_repo_name, + GH_REPO_DESC: github_desc, + GH_REPO_HOMEPAGE: url + } + } + ], + depends_on: + [ + "push-"+version.tag + for version in versions + ] +}; + + + + build_pipelines(architectures) + push_pipelines(versions,architectures) + [push_github] + + [ +{ + kind: "secret", + name: "GH_TOKEN", + get:{ + path: "github", + name: "token" + } +}, +{ + kind: "secret", + name: "username", + get:{ + path: "docker", + name: "username" + } +}, +{ + kind: "secret", + name: "password", + get:{ + path: "docker", + name: "secret" + } +} + ] diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..888587c --- /dev/null +++ b/Containerfile @@ -0,0 +1,47 @@ +FROM alpine:latest AS qpsmtpd-setup + +RUN apk update && apk add --no-cache git + +WORKDIR /tmp + +# use the repository fork of byterazor because of additional plugins +RUN git clone https://gitea.federationhq.de/byterazor/qpsmtpd.git +RUN cd /tmp/qpsmtpd;git checkout rcpt_mysql + +FROM debian:stable-slim + +RUN apt-get update && apt-get -qy install perl tini bash + +# qpsmtpd dependencies +RUN apt-get -qy install libnet-dns-perl libmime-base64-urlsafe-perl libtimedate-perl +RUN apt-get -qy install libmailtools-perl libnet-ip-perl libdbd-mariadb-perl libdbd-mysql-perl + + +# qpsmtpd runs under the smtpd user +RUN adduser -u 34342 --disabled-login smtpd +RUN mkdir -p /usr/share/qpsmtpd + +COPY --from=qpsmtpd-setup /tmp/qpsmtpd/qpsmtpd /usr/bin/ +COPY --from=qpsmtpd-setup /tmp/qpsmtpd/qpsmtpd-forkserver /usr/bin/ +COPY --from=qpsmtpd-setup /tmp/qpsmtpd/qpsmtpd-prefork /usr/bin/ +COPY --from=qpsmtpd-setup /tmp/qpsmtpd/plugins /usr/share/qpsmtpd/plugins +COPY --from=qpsmtpd-setup /tmp/qpsmtpd/lib /usr/share/perl5/ + +# create spool directory +RUN mkdir -p /var/spool/qpsmtpd +RUN chown smtpd:smtpd /var/spool/qpsmtpd +RUN chmod 0700 /var/spool/qpsmtpd + +# create base configuration +RUN mkdir -p /etc/qpsmtpd +COPY config /etc/qpsmtpd +RUN chown -R smtpd:smtpd /etc/qpsmtpd + + +ADD scripts/entryPoint.sh /entryPoint.sh +ADD scripts/plugins/ /plugins/ +RUN chmod -R a+x /plugins/* +RUN chmod a+x /entryPoint.sh + +ENTRYPOINT ["/usr/bin/tini", "--", "/entryPoint.sh"] + diff --git a/config/IP b/config/IP new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/config/IP @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/config/dnsbl_zones b/config/dnsbl_zones new file mode 100644 index 0000000..0db56e6 --- /dev/null +++ b/config/dnsbl_zones @@ -0,0 +1,2 @@ +spamsources.fabel.dk +zen.spamhaus.org \ No newline at end of file diff --git a/config/karma_tlds b/config/karma_tlds new file mode 100644 index 0000000..6ef0762 --- /dev/null +++ b/config/karma_tlds @@ -0,0 +1 @@ +ru: -5 \ No newline at end of file diff --git a/config/plugin_dirs b/config/plugin_dirs new file mode 100644 index 0000000..805b6b8 --- /dev/null +++ b/config/plugin_dirs @@ -0,0 +1 @@ +/usr/share/qpsmtpd/plugins \ No newline at end of file diff --git a/config/rhsbl_zones b/config/rhsbl_zones new file mode 100644 index 0000000..fd4f969 --- /dev/null +++ b/config/rhsbl_zones @@ -0,0 +1 @@ +dsn.rfc-ignorant.org does not accept bounces. This violates RFC 821/2505/2821 http://www.rfc-ignorant.org/ \ No newline at end of file diff --git a/config/size_threshold b/config/size_threshold new file mode 100644 index 0000000..1746da6 --- /dev/null +++ b/config/size_threshold @@ -0,0 +1 @@ +10000 \ No newline at end of file diff --git a/config/spool_dir b/config/spool_dir new file mode 100644 index 0000000..041a649 --- /dev/null +++ b/config/spool_dir @@ -0,0 +1 @@ +/var/spool/qpsmtpd/ \ No newline at end of file diff --git a/config/tls_before_auth b/config/tls_before_auth new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/config/tls_before_auth @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/config/tls_ciphers b/config/tls_ciphers new file mode 100644 index 0000000..18a0727 --- /dev/null +++ b/config/tls_ciphers @@ -0,0 +1 @@ +HIGH:!SSLv2 \ No newline at end of file diff --git a/scripts/entryPoint.sh b/scripts/entryPoint.sh new file mode 100644 index 0000000..4fb23c3 --- /dev/null +++ b/scripts/entryPoint.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# +# ensure some directories exist and have the correct access rights +# +mkdir -p /var/spool/qpsmtpd/karma +chown -R smtpd:smtpd /var/spool/qpsmtpd + + +if [ -z ${QPSMTPD_PORT} ]; then + QPSMTPD_PORT=25 +fi + +if [ -z ${QPSMTPD_CONCURRENT_CONNECTIONS} ]; then + QPSMTPD_CONCURRENT_CONNECTIONS=15 +fi + +if [ -z ${QPSMTPD_MAX_FROM_IP} ]; then + QPSMTPD_MAX_FROM_IP=5 +fi + +if [ -z ${QPSMTPD_LOGLEVEL} ]; then + QPSMTPD_LOGLEVEL=3 +fi + +if [ -n "${QPSMTPD_RELAY}" ]; then + rm -rf /etc/qpsmtpd/relayclients + for i in ${QPSMTPD_RELAY}; do + echo $i >> /etc/qpsmtpd/relayclients + done +fi + +if [ -z "${QPSMTPD_SMTP_RELAY_HOST}" ]; then + echo "please provide QPSMTPD_SMTP_RELAY_HOST" + exit 255 +fi + +if [ -n "${QPSMTPD_RECIPIENTS}" ]; then + rm -rf /etc/qpsmtpd/rcpthosts + for i in ${QPSMTPD_RECIPIENTS}; do + echo $i >> /etc/qpsmtpd/rcpthosts + done +fi + + + +export QPSMTPD_CONFIG="/etc/qpsmtpd" + +echo ${QPSMTPD_LOGLEVEL} > /etc/qpsmtpd/loglevel + + +# +# generate the plugins configuration file for qpsmtpd +# + +if [ -n "${QPSMTPD_ENABLE_EARLYTALKER}" ]; then + echo "earlytalker ${QPSMTPD_EARLYTALKER_PARAMS}" +fi + +if [ -n "${QPSMTPD_ENABLE_TLS}" ]; then + echo "tls" >> /etc/qpsmtpd/plugins +fi + +echo "relay" >> /etc/qpsmtpd/plugins +echo "hosts_allow" >> /etc/qpsmtpd/plugins + +echo "karma db_dir /var/spool/qpsmtpd/karma penalty_box 1 reject naughty" >> /etc/qpsmtpd/plugins +echo "fcrdns has_reverse_dns has_forward_dns reject naughty" >> /etc/qpsmtpd/plugins +echo "dnsbl reject naughty reject_type disconnect" >> /etc/qpsmtpd/plugins +echo "rhsbl" >> /etc/qpsmtpd/plugins +echo "resolvable_fromhost reject naughty" >> /etc/qpsmtpd/plugins +echo "bogus_bounce" >> /etc/qpsmtpd/plugins + +# +# all recipient plugins +# + +/plugins/rcpt_mysql + +echo "rcpt_ok" >> /etc/qpsmtpd/plugins + +# +# finish the configuration +# +echo "naughty reject data" >> /etc/qpsmtpd/plugins + +# +# setup final queuing +# +echo "queue/smtp-forward ${QPSMTPD_SMTP_RELAY_HOST}" + +# start the forkserver of qpsmtpd +qpsmtpd-forkserver -p ${QPSMTPD_PORT} -c ${QPSMTPD_CONCURRENT_CONNECTIONS} -m ${QPSMTPD_MAX_FROM_IP} diff --git a/scripts/plugins/rcpt_mysql b/scripts/plugins/rcpt_mysql new file mode 100644 index 0000000..1a42e48 --- /dev/null +++ b/scripts/plugins/rcpt_mysql @@ -0,0 +1,55 @@ +#!/bin/bash + +if [ -n "${QPSMTPD_ENABLE_RCPT_MYSQL}" ]; then + + if [ -z "${QPSMTPD_RCPT_MYSQL_DATABASE}" ]; then + echo "missing QPSMTPD_RCPT_MYSQL_DATABASE" + exit 255 + fi + + if [ -z "${QPSMTPD_RCPT_MYSQL_PORT}" ]; then + QPSMTPD_RCPT_MYSQL_PORT=3306 + fi + + if [ -z "${QPSMTPD_RCPT_MYSQL_CACHETIMEOUT}" ]; then + QPSMTPD_RCPT_MYSQL_CACHETIMEOUT=500 + fi + + if [ -z "${QPSMTPD_RCPT_MYSQL_HOST}" ]; then + echo "missing QPSMTPD_RCPT_MYSQL_HOST" + exit 255 + fi + + if [ -z "${QPSMTPD_RCPT_MYSQL_USER}" ]; then + echo "missing QPSMTPD_RCPT_MYSQL_USER" + exit 255 + fi + + if [ -z "${QPSMTPD_RCPT_MYSQL_PASS}" ]; then + echo "missing QPSMTPD_RCPT_MYSQL_DATABASE" + exit 255 + fi + + if [ -z "${QPSMTPD_RCPT_MYSQL_QUERY}" ]; then + echo "missing QPSMTPD_RCPT_MYSQL_QUERY" + exit 255 + fi + + # + # create configuration file + # + rm -rf /etc/qpsmtpd/rcpt_mysql + echo "database:=${QPSMTPD_RCPT_MYSQL_DATABASE}" >> /etc/qpsmtpd/rcpt_mysql + echo "host:=${QPSMTPD_RCPT_MYSQL_HOST}" >> /etc/qpsmtpd/rcpt_mysql + echo "port:=${QPSMTPD_RCPT_MYSQL_PORT}" >> /etc/qpsmtpd/rcpt_mysql + echo "user:=${QPSMTPD_RCPT_MYSQL_USER}" >> /etc/qpsmtpd/rcpt_mysql + echo "pass:=${QPSMTPD_RCPT_MYSQL_PASS}" >> /etc/qpsmtpd/rcpt_mysql + echo "host:=${QPSMTPD_RCPT_MYSQL_HOST}" >> /etc/qpsmtpd/rcpt_mysql + echo "cachetimeout:=${QPSMTPD_RCPT_MYSQL_CACHETIMEOUT}" >> /etc/qpsmtpd/rcpt_mysql + echo "query:=${QPSMTPD_RCPT_MYSQL_QUERY}" >> /etc/qpsmtpd/rcpt_mysql + + + # enable plugin + echo "rcpt_mysql" >> /etc/qpsmtpd/plugins + +fi diff --git a/scripts/setupEnvironment.sh b/scripts/setupEnvironment.sh new file mode 100755 index 0000000..2761ce0 --- /dev/null +++ b/scripts/setupEnvironment.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cp /etc/ssl/certs2/federationHQ-CA.pem /etc/pki/ca-trust/source/anchors/ +update-ca-trust