From 0c12027622fec8c700fc590edef8cf23f40c88b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bojan=20=C4=8Cekrli=C4=87?= Date: Sat, 29 May 2021 17:08:08 +0200 Subject: [PATCH] New: Add support for Ubuntu builds and TLS certs on Helm --- .github/workflows/master.yml | 12 ++++++-- .github/workflows/tags.yml | 10 +++++-- Dockerfile | 42 +++++++++++++++++++++------- alpine-versions.sh | 2 +- helm/mail/templates/_helpers.tpl | 1 + helm/mail/templates/configmap.yaml | 7 +++++ helm/mail/templates/secret-cert.yaml | 22 +++++++++++++++ helm/mail/templates/statefulset.yaml | 17 +++++++++++ helm/mail/values.yaml | 14 ++++++++-- helm/test_7_certs.yml | 2 ++ scripts/common-run.sh | 31 +++++++++++++++----- 11 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 helm/mail/templates/secret-cert.yaml create mode 100644 helm/test_7_certs.yml diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 1e5c148..dfbbf34 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -38,9 +38,15 @@ jobs: ./integration-tests.sh - name: Run HELM chart tests run: ./helm/tests.sh - - name: Build master + - name: Build Alpine master env: DOCKER_USERNAME: 'boky' DOCKER_PASSWORD: '${{ secrets.DOCKER_ACCESS_TOKEN }}' - PLATFORMS: "linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le" - run: ./build.sh -t boky/postfix --push + PLATFORMS: "linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x" + run: ./build.sh -t boky/postfix:latest --push + - name: Build Ubuntu master + env: + DOCKER_USERNAME: 'boky' + DOCKER_PASSWORD: '${{ secrets.DOCKER_ACCESS_TOKEN }}' + PLATFORMS: "linux/386,linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x" + run: ./build.sh -t boky/postfix:ubuntu-latest --push diff --git a/.github/workflows/tags.yml b/.github/workflows/tags.yml index 350eef3..7ad12b3 100644 --- a/.github/workflows/tags.yml +++ b/.github/workflows/tags.yml @@ -29,12 +29,18 @@ jobs: uses: crazy-max/ghaction-docker-buildx@v1 with: buildx-version: latest - - name: Build branch / tag + - name: Build Alpine tag env: DOCKER_USERNAME: 'boky' DOCKER_PASSWORD: '${{ secrets.DOCKER_ACCESS_TOKEN }}' - PLATFORMS: "linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le" + PLATFORMS: "linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x" run: ./build.sh -t boky/postfix:$RELEASE_VERSION --push + - name: Build Ubuntu tag + env: + DOCKER_USERNAME: 'boky' + DOCKER_PASSWORD: '${{ secrets.DOCKER_ACCESS_TOKEN }}' + PLATFORMS: "linux/386,linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x" + run: ./build.sh -t boky/postfix:ubuntu-$RELEASE_VERSION --push - name: Copy `README.md` and `LICENCE` into the helm chart id: readme_and_licence shell: bash diff --git a/Dockerfile b/Dockerfile index f41df00..01676f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,23 @@ -ARG ALPINE_VERSION=latest -FROM alpine:${ALPINE_VERSION} as build +ARG BASE_IMAGE=alpine:latest +# ARG BASE_IMAGE=ubuntu:focal +# ============================ BUILD SASL XOAUTH2 ============================ +FROM ${BASE_IMAGE} as build ARG SASL_XOAUTH2_REPO_URL=https://github.com/tarickb/sasl-xoauth2.git ARG SASL_XOAUTH2_GIT_REF=release-0.10 RUN true && \ - apk add --no-cache --upgrade git && \ - apk add --no-cache --upgrade cmake clang make gcc g++ libc-dev pkgconfig curl-dev jsoncpp-dev cyrus-sasl-dev && \ + if [ -f /etc/alpine-release ]; then \ + apk add --no-cache --upgrade git && \ + apk add --no-cache --upgrade cmake clang make gcc g++ libc-dev pkgconfig curl-dev jsoncpp-dev cyrus-sasl-dev; \ + else \ + export DEBIAN_FRONTEND=noninteractive && \ + echo "Europe/Berlin" > /etc/timezone && \ + apt-get update -y -q && \ + apt-get install -y git build-essential cmake pkg-config libcurl4-nss-dev libjsoncpp-dev libsasl2-dev; \ + fi + +RUN true && \ git clone --depth 1 --branch ${SASL_XOAUTH2_GIT_REF} ${SASL_XOAUTH2_REPO_URL} /sasl-xoauth2 && \ cd /sasl-xoauth2 && \ mkdir build && \ @@ -14,18 +25,29 @@ RUN true && \ cmake -DCMAKE_INSTALL_PREFIX=/ .. && \ make -FROM alpine:${ALPINE_VERSION} +# ============================ BUILD SASL XOAUTH2 ============================ +FROM ${BASE_IMAGE} LABEL maintaner="Bojan Cekrlic - https://github.com/bokysan/docker-postfix/" # Install supervisor, postfix # Install postfix first to get the first account (101) # Install opendkim second to get the second account (102) RUN true && \ - apk add --no-cache --upgrade cyrus-sasl cyrus-sasl-static cyrus-sasl-digestmd5 cyrus-sasl-crammd5 cyrus-sasl-login cyrus-sasl-ntlm && \ - apk add --no-cache postfix && \ - apk add --no-cache opendkim && \ - apk add --no-cache --upgrade ca-certificates tzdata supervisor rsyslog musl musl-utils bash opendkim-utils libcurl jsoncpp lmdb && \ - (rm "/tmp/"* 2>/dev/null || true) && (rm -rf /var/cache/apk/* 2>/dev/null || true) && \ + if [ -f /etc/alpine-release ]; then \ + apk add --no-cache --upgrade cyrus-sasl cyrus-sasl-static cyrus-sasl-digestmd5 cyrus-sasl-crammd5 cyrus-sasl-login cyrus-sasl-ntlm && \ + apk add --no-cache postfix && \ + apk add --no-cache opendkim && \ + apk add --no-cache --upgrade ca-certificates tzdata supervisor rsyslog musl musl-utils bash opendkim-utils libcurl jsoncpp lmdb && \ + (rm "/tmp/"* 2>/dev/null || true) && (rm -rf /var/cache/apk/* 2>/dev/null || true); \ + else \ + export DEBIAN_FRONTEND=noninteractive && \ + echo "Europe/Berlin" > /etc/timezone && \ + apt-get update -y -q && \ + apt-get install -y libsasl2-modules && \ + apt-get install -y postfix && \ + apt-get install -y opendkim && \ + apt-get install -y ca-certificates tzdata supervisor rsyslog bash opendkim-tools curl libcurl4 libjsoncpp1 postfix-lmdb netcat; \ + fi && \ cp -r /etc/postfix /etc/postfix.template # Copy SASL-XOAUTH2 plugin diff --git a/alpine-versions.sh b/alpine-versions.sh index 2fb866e..51fded3 100755 --- a/alpine-versions.sh +++ b/alpine-versions.sh @@ -12,5 +12,5 @@ docker login # build, tag, and push alpine versions supplied as script arguments base_repo=boky/postfix for alpine_version in "$@"; do - $(dirname $0)/build.sh -t "$base_repo" --build-arg=ALPINE_VERSION="$alpine_version" + $(dirname $0)/build.sh -t "$base_repo" --build-arg=BASE_IMAGE="alpine:$alpine_version" done diff --git a/helm/mail/templates/_helpers.tpl b/helm/mail/templates/_helpers.tpl index 0938c8b..a4ef7f0 100644 --- a/helm/mail/templates/_helpers.tpl +++ b/helm/mail/templates/_helpers.tpl @@ -75,3 +75,4 @@ checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | # Uses: https://github.com/stakater/Reloader configmap.reloader.stakater.com/reload: "{{ include "mail.fullname" . }}" {{- end -}} + diff --git a/helm/mail/templates/configmap.yaml b/helm/mail/templates/configmap.yaml index 5b94586..c3621f6 100644 --- a/helm/mail/templates/configmap.yaml +++ b/helm/mail/templates/configmap.yaml @@ -16,3 +16,10 @@ data: {{- range $key, $value := .Values.config.opendkim }} OPENDKIM_{{ $key }}: {{ $value | quote }} {{- end }} + {{- if .Values.certs.create }} + _enable_tls.sh: | + do_postconf -e 'smtp_use_tls=yes' + do_postconf -e 'smtp_tls_note_starttls_offer=yes' + do_postconf -e 'smtpd_tls_cert_file=/var/run/certs/tls.crt' + do_postconf -e 'smtpd_tls_key_file=/var/run/certs/tls.key' + {{- end }} diff --git a/helm/mail/templates/secret-cert.yaml b/helm/mail/templates/secret-cert.yaml new file mode 100644 index 0000000..948aa45 --- /dev/null +++ b/helm/mail/templates/secret-cert.yaml @@ -0,0 +1,22 @@ +{{- if .Values.certs.create -}} +{{/* Generate certificates for mail server */}} +{{- $chart := "mail" -}} +{{- $fullName := include (print $chart ".fullname") . -}} +{{- $labels := include (print $chart ".labels") . -}} +{{- $altNames := list ( printf "%s.%s" $fullName .Release.Namespace ) ( printf "%s.%s.svc" $fullName .Release.Namespace ) ( printf "%s.%s.svc.cluster.local" $fullName .Release.Namespace ) -}} +{{- $ca := genCA "mail-ca" 365 -}} +{{- $cert := genSignedCert ( include "mail.name" . ) nil $altNames 365 $ca -}} +apiVersion: v1 +kind: Secret +type: kubernetes.io/tls +metadata: + name: {{ $fullName }}-certs + labels: + {{- $labels | nindent 4 }} + annotations: + "helm.sh/hook": "pre-install" + "helm.sh/hook-delete-policy": "before-hook-creation" +data: + tls.crt: {{ $cert.Cert | b64enc }} + tls.key: {{ $cert.Key | b64enc }} +{{- end }} diff --git a/helm/mail/templates/statefulset.yaml b/helm/mail/templates/statefulset.yaml index 460ddf6..c3a0ff2 100644 --- a/helm/mail/templates/statefulset.yaml +++ b/helm/mail/templates/statefulset.yaml @@ -80,6 +80,15 @@ spec: name: private - mountPath: /var/spool/postfix/public name: private + {{- if .Values.certs.create }} + - name: certs + mountPath: /var/run/certs + readOnly: true + - name: certs-init + mountPath: /docker-init.db/_enable_tls.sh + readOnly: true + subPath: _enable_tls.sh + {{- end }} {{- if .Values.extraVolumeMounts }}{{- toYaml .Values.extraVolumeMounts | nindent 12 }}{{ end }} resources: {{ toYaml .Values.resources | nindent 12 }} volumes: @@ -88,6 +97,14 @@ spec: emptyDir: {} - name: private emptyDir: {} + {{- if .Values.certs.create }} + - name: certs-init + secret: + configMapName: {{ $fullName }} + - name: certs + secret: + secretName: {{ $fullName }}-certs + {{- end }} {{- if and .Values.persistence.enabled .Values.persistence.existingClaim }} - name: {{ $fullName }} persistentVolumeClaim: diff --git a/helm/mail/values.yaml b/helm/mail/values.yaml index 3929087..d120288 100644 --- a/helm/mail/values.yaml +++ b/helm/mail/values.yaml @@ -68,10 +68,15 @@ container: postfix: securityContext: {} +# Auto-generate certificates for the server and mount them into Postfix volume +certs: + create: true + # Define data which should be stored in a Secret # (and shared with the pod as environment variables) # secret: # hello: world +secret: {} config: general: {} @@ -123,7 +128,9 @@ livenessProbe: command: - sh - -c - - 'ps axf | fgrep -v grep | fgrep -q "{supervisord}" && ps axf | fgrep -v grep | fgrep -q "/usr/libexec/postfix/master"' + - >- + ps axf | fgrep -v grep | egrep -q '\{supervisord\}|/usr/bin/supervisord' && + ps axf | fgrep -v grep | egrep -q '(/usr/lib/postfix/sbin/|/usr/libexec/postfix/)master' startupProbe: initialDelaySeconds: 5 periodSeconds: 5 @@ -132,4 +139,7 @@ startupProbe: command: - sh - -c - - 'ps axf | fgrep -v grep | fgrep -q "{supervisord}" && ps axf | fgrep -v grep | fgrep -q "{postfix-script}" && ps axf | fgrep -v grep | fgrep -q "{opendkim.sh}"' + - >- + ps axf | fgrep -v grep | egrep -q '\{supervisord\}|/usr/bin/supervisord' && + ps axf | fgrep -v grep | fgrep -q "postfix-script" && + ps axf | fgrep -v grep | fgrep -q 'opendkim.sh' diff --git a/helm/test_7_certs.yml b/helm/test_7_certs.yml new file mode 100644 index 0000000..dad2fc9 --- /dev/null +++ b/helm/test_7_certs.yml @@ -0,0 +1,2 @@ +certs: + create: true \ No newline at end of file diff --git a/scripts/common-run.sh b/scripts/common-run.sh index ca46ea5..c526e5f 100644 --- a/scripts/common-run.sh +++ b/scripts/common-run.sh @@ -50,38 +50,55 @@ setup_conf() { } reown_folders() { - mkdir -p /var/spool/postfix/ && mkdir -p /var/spool/postfix/pid + mkdir -p /var/spool/postfix/pid /var/spool/postfix/dev chown root: /var/spool/postfix/ chown root: /var/spool/postfix/pid + + do_postconf -e "manpage_directory=/usr/share/man" + postfix -c /etc/postfix/ set-permissions || true } postfix_upgrade_conf() { local maincf=/etc/postfix/main.cf + local line local entry local filename + local OLD_IFS # Check for any references to the old "hash:" and "btree:" databases and replae them with "lmdb:" if cat "$maincf" | egrep -v "^#" | egrep -q "(hash|btree):"; then - info "Detected old hash: and btree: references in the config file, which are not supported anymore. Upgrading to lmdb:" + warn "Detected old hash: and btree: references in the config file, which are not supported anymore. Upgrading to lmdb:" sed -i -E 's/(hash|btree):/lmdb:/g' "$maincf" + OLD_IFS="$IFS" + IFS=$'\n' # Recreate aliases - for entry in $(cat "$maincf" | egrep -o "lmdb:[^,]+" | sort | uniq); do - filename="$(echo $entry | cut -d: -f2)" + for line in $(cat "$maincf" | egrep 'lmdb:[^,]+' | sort | uniq); do + entry="$(echo "$line" | egrep -o 'lmdb:[^,]+')" + filename="$(echo "$entry" | cut -d: -f2)" if [[ -f "$filename" ]]; then - debug "Creating new postmap for ${emphasis}$entry${reset}." - postmap $entry + if echo "$line" | egrep -q '[ \t]*alias.*'; then + debug "Creating new postalias for ${emphasis}$entry${reset}." + postalias $entry + else + debug "Creating new postmap for ${emphasis}$entry${reset}." + postmap $entry + fi fi done + IFS="$OLD_IFS" else debug "No upgrade needed." fi } postfix_disable_utf8() { - do_postconf -e smtputf8_enable=no + if [[ -f /etc/alpine-release ]]; then + do_postconf -e smtputf8_enable=no + fi } postfix_create_aliases() { + touch /etc/postfix/aliases postalias /etc/postfix/aliases }