diff options
author | Gilles Chehade <gilles@poolp.org> | 2020-04-30 02:06:46 +0200 |
---|---|---|
committer | Gilles Chehade <gilles@poolp.org> | 2020-04-30 02:06:46 +0200 |
commit | d4180f85d53f7381da9fcc7257cf61d0b29497a0 (patch) | |
tree | 928f5541f702f22aec334cd7262d611821ff44cf /ci | |
parent | Merge remote-tracking branch 'portable/native' (diff) | |
download | OpenSMTPD-d4180f85d53f7381da9fcc7257cf61d0b29497a0.tar.xz OpenSMTPD-d4180f85d53f7381da9fcc7257cf61d0b29497a0.zip |
merge histories
Diffstat (limited to 'ci')
-rw-r--r-- | ci/COVERITY.MD5SUM | 1 | ||||
-rw-r--r-- | ci/README.md | 83 | ||||
-rw-r--r-- | ci/docker/Dockerfile.alpine | 50 | ||||
-rw-r--r-- | ci/docker/Dockerfile.archlinux | 62 | ||||
-rw-r--r-- | ci/docker/Dockerfile.ubuntu | 52 | ||||
-rw-r--r-- | ci/docker/Dockerfile.ubuntu-gcc10 | 54 | ||||
-rwxr-xr-x | ci/scripts/clang_scan.sh | 60 | ||||
-rwxr-xr-x | ci/scripts/coverity_scan.sh | 77 | ||||
-rwxr-xr-x | ci/scripts/generate_certs.sh | 33 | ||||
-rw-r--r-- | ci/scripts/imports/badge.sh | 72 | ||||
-rw-r--r-- | ci/scripts/ssl.conf | 23 |
11 files changed, 567 insertions, 0 deletions
diff --git a/ci/COVERITY.MD5SUM b/ci/COVERITY.MD5SUM new file mode 100644 index 00000000..67b8a2de --- /dev/null +++ b/ci/COVERITY.MD5SUM @@ -0,0 +1 @@ +d0d7d7df9d6609e578f85096a755fb8f ./cov-analysis-linux64.tgz diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 00000000..2eee08f1 --- /dev/null +++ b/ci/README.md @@ -0,0 +1,83 @@ +# Continuous Integration + +This directory contains CI/CD related scripts and resources + +CI/CD process leverages GitHub Actions as a primary automation platform since +up to 20 parallel workflows are available for opensource projects. + +On high level we have multiple dimensions to test: + + - OS Distribution + - TLS library implementation: libress, openssl + - libc implementations: glibc, musl + - compiler: gcc, clang (not yet tested) + +Within this matrix build tests, static code analysis, functional and +integration tests are planned. Currently only build tests and static code +analysis exist. Help is much needed with developing functional and integration +tests. + +## Directory strucuture + +- [docker](#dockerfiles) dockerfiles for various distributions +- [scripts](#scripts) useful scripts for ci/cd automation + + +## Design Considerations + +- Keep workflow yaml files and execution logic as separate as possible. + Reference ci scripts from workflow files to allow running same tests + locally, without depending on github. + + + +# Dockerfiles + +Dockerfiles in [docker](docker/) directory can be used for developing and +testing OpenSMTPD. These dockerfiles are intended to be used for dev/test +cycle ONLY and ARE NOT intended to be a delivery mechanism for end users and +should not be published on external resouces like DockerHub. Dockerfiles in +this folder can be used as a reference for package maintainers of various +distributions. + + +## Usage + +OpenSMTPD provides a set of dockerfiles for getting started with development +quickly locally or with GitHub's Actions. + +For each distribution there is a separate dockerfile with a distro name +suffixed. E.g. `Dockerfile.alpine` is a dockerfile that builds OpenSMTPD in +Alpine Linux environment. + +To build: + + docker build -f docker/Dockerfile.alpine -t opensmtpd-alpine + + +All configuration files that are in `/etc/mail` are taken from `etc/` directory. + + +To run the container that you've just built run: + + docker run --name smtpd_server -p 25:25 opensmtpd-alpine + + + +# Scripts + +Scripts to automate ci/cd actions: + +- [coverity_scan](scripts/coverity_scan.sh) - runs coverity scan and submits + the rusult to Coverity. See script contents for usage instructions. + +- [generate_certs](scripts/generate_certs.sh) - convenient script to quickly + generate some TLS certificates. Useful for testing. + +# Historical reference + +[Initial design discusstion](https://github.com/OpenSMTPD/OpenSMTPD/issues/947) + + + + diff --git a/ci/docker/Dockerfile.alpine b/ci/docker/Dockerfile.alpine new file mode 100644 index 00000000..2c7c66fc --- /dev/null +++ b/ci/docker/Dockerfile.alpine @@ -0,0 +1,50 @@ +FROM alpine:3.11 as build + +# creates /opensmtpd dir and makes all following commands to run in it +# https://docs.docker.com/engine/reference/builder/#workdir +WORKDIR /opensmtpd + +# install necessary packages +RUN apk add --no-cache \ + autoconf \ + automake \ + bison \ + ca-certificates \ + fts-dev \ + gcc \ + fts \ + libevent-dev \ + libtool \ + libtool \ + linux-pam-dev \ + make \ + musl-dev \ + libressl \ + libressl-dev \ + zlib-dev + +# create users and directories +# note: alpine uses busybox and useradd is not available there +# also long flags are not available too, so sorry for the +RUN mkdir -p /var/lib/opensmtpd/empty \ + && adduser _smtpd -h /var/lib/opensmtpd/empty/ -D -H -s /bin/false \ + && adduser _smtpq -h /var/lib/opensmtpd/empty/ -D -H -s /bin/false \ + && mkdir -p /var/spool/smtpd \ + && mkdir -p /var/mail \ + && mkdir -p /etc/mail \ + && chmod 711 /var/spool/smtpd + +# Copy contentes of the repo inside the container +# https://docs.docker.com/engine/reference/builder/#copy +COPY . /opensmtpd + +# build opensmtpd +RUN ./bootstrap \ + && ./configure \ + --with-gnu-ld \ + --sysconfdir=/etc/mail \ + --with-auth-pam \ + && make \ + && make install \ + && cp etc/aliases /etc/mail/aliases + diff --git a/ci/docker/Dockerfile.archlinux b/ci/docker/Dockerfile.archlinux new file mode 100644 index 00000000..dcd46684 --- /dev/null +++ b/ci/docker/Dockerfile.archlinux @@ -0,0 +1,62 @@ +FROM archlinux + +# Allow container to expose ports at runtime, if necessary +# https://docs.docker.com/engine/reference/#expose +EXPOSE 25 +EXPOSE 465 +EXPOSE 587 + +# creates /opensmtpd dir and makes all following commands to run in it +# https://docs.docker.com/engine/reference/builder/#workdir +WORKDIR /opensmtpd + +# install necessary packages +RUN pacman -Suy --noconfirm \ + base \ + make \ + m4 \ + grep \ + gcc \ + automake \ + autoconf \ + libtool \ + bison \ + gettext \ + libevent \ + libressl \ + pam \ + zlib + + +# create users and directories +RUN mkdir -p /var/lib/opensmtpd/empty \ + && useradd _smtpd \ + --home-dir /var/lib/opensmtpd/empty \ + --no-create-home \ + --shell /bin/false \ + && useradd _smtpq \ + --home-dir /var/lib/opensmtpd/empty \ + --no-create-home \ + --shell /bin/false \ + && mkdir -p /var/spool/smtpd \ + && mkdir -p /var/mail \ + && mkdir -p /etc/mail \ + && chmod 711 /var/spool/smtpd + + +# Copy contentes of the repo inside the container +# https://docs.docker.com/engine/reference/builder/#copy +COPY . /opensmtpd + + +# build opensmtpd +RUN ./bootstrap \ + && ./configure --with-gnu-ld \ + --sysconfdir=/etc/mail \ + --with-cflags='-I/usr/include/libressl -L/usr/lib/libressl -Wl,-rpath=/usr/lib/libressl' \ + --with-path-empty=/var/lib/opensmtpd/empty \ + --with-auth-pam \ + && make \ + && make install \ + && cp etc/aliases /etc/mail/aliases + diff --git a/ci/docker/Dockerfile.ubuntu b/ci/docker/Dockerfile.ubuntu new file mode 100644 index 00000000..6626033d --- /dev/null +++ b/ci/docker/Dockerfile.ubuntu @@ -0,0 +1,52 @@ +FROM ubuntu:latest + +# Allow container to expose ports at runtime, if necessary +# https://docs.docker.com/engine/reference/#expose +EXPOSE 25 +EXPOSE 465 +EXPOSE 587 + +# creates /opensmtpd dir and makes all following commands to run in it +# https://docs.docker.com/engine/reference/builder/#workdir +WORKDIR /opensmtpd + +# install necessary packages +RUN apt update \ + && apt install -y --no-install-recommends \ + autoconf \ + automake \ + bison \ + build-essential \ + libevent-dev \ + libssl-dev \ + libtool \ + libpam0g-dev \ + zlib1g-dev + +# create users and directories +RUN mkdir -p /var/lib/opensmtpd/empty \ + && useradd _smtpd \ + --home-dir /var/lib/opensmtpd/empty \ + --no-create-home \ + --shell /bin/false \ + && useradd _smtpq \ + --home-dir /var/lib/opensmtpd/empty \ + --no-create-home \ + --shell /bin/false \ + && mkdir -p /var/spool/smtpd \ + && mkdir -p /var/mail \ + && mkdir -p /etc/mail \ + && chmod 711 /var/spool/smtpd + +# Copy contentes of the repo inside the container +# https://docs.docker.com/engine/reference/builder/#copy +COPY . /opensmtpd + +RUN ./bootstrap \ + && ./configure \ + --with-gnu-ld \ + --sysconfdir=/etc/mail \ + --with-auth-pam \ + && make \ + && make install \ + && cp etc/aliases /etc/mail/aliases diff --git a/ci/docker/Dockerfile.ubuntu-gcc10 b/ci/docker/Dockerfile.ubuntu-gcc10 new file mode 100644 index 00000000..2ebbdf58 --- /dev/null +++ b/ci/docker/Dockerfile.ubuntu-gcc10 @@ -0,0 +1,54 @@ +FROM ubuntu:latest + +# Allow container to expose ports at runtime, if necessary +# https://docs.docker.com/engine/reference/#expose +EXPOSE 25 +EXPOSE 465 +EXPOSE 587 + +# creates /opensmtpd dir and makes all following commands to run in it +# https://docs.docker.com/engine/reference/builder/#workdir +WORKDIR /opensmtpd + +# install necessary packages +RUN apt update \ + && apt install -y --no-install-recommends \ + autoconf \ + automake \ + bison \ + build-essential \ + libevent-dev \ + libssl-dev \ + libtool \ + libpam0g-dev \ + zlib1g-dev \ + gcc-10 + +# create users and directories +RUN mkdir -p /var/lib/opensmtpd/empty \ + && useradd _smtpd \ + --home-dir /var/lib/opensmtpd/empty \ + --no-create-home \ + --shell /bin/false \ + && useradd _smtpq \ + --home-dir /var/lib/opensmtpd/empty \ + --no-create-home \ + --shell /bin/false \ + && mkdir -p /var/spool/smtpd \ + && mkdir -p /var/mail \ + && mkdir -p /etc/mail \ + && chmod 711 /var/spool/smtpd + +# Copy contentes of the repo inside the container +# https://docs.docker.com/engine/reference/builder/#copy +COPY . /opensmtpd + +RUN export CC=gcc-10 CXX=g++-10 +RUN ./bootstrap \ + && ./configure \ + --with-gnu-ld \ + --sysconfdir=/etc/mail \ + --with-auth-pam \ + && make \ + && make install \ + && cp etc/aliases /etc/mail/aliases diff --git a/ci/scripts/clang_scan.sh b/ci/scripts/clang_scan.sh new file mode 100755 index 00000000..714d55a7 --- /dev/null +++ b/ci/scripts/clang_scan.sh @@ -0,0 +1,60 @@ +#!/bin/sh +set -eu + +# Unconditionally go to the root level of the git repo. +# If you invoke it from outside of the repo go to +# the script location first +cd "$(dirname "$0")" +cd "$(git rev-parse --show-toplevel)" + +# Clang Scan script +# +# USAGE: +# - clang must be installed +# - make sure you have clean repository, +# e.g. git clean -ffdx +# - if you want to download github badge set CLANG_SCAN_BADGE_REQUIRED variable +# - Run script from anywhere inside the repository +# ./ci/scripts/clang_scan.sh +# or +# CLANG_SCAN_BADGE_REQUIRED=1 ./ci/scripts/clang_scan.sh +# + +if ! type scan-build > /dev/null; then + echo "clang scan-build is missing" + exit 1 +fi + +# Unconditionally go to the root level of the git repo. +# If you invoke it from outside of the repo go to +# the script location first +cd "$(dirname "$0")" +# This moves us to the root of the repo +cd "$(git rev-parse --show-toplevel)" + +# Get short SHA of the HEAD +sha=$(git rev-parse --short HEAD) + +results_dir=${CLANG_SCAN_RESULTS_DIR:-clang-report} +mkdir -p "$results_dir" + +# Build with scan-build +./bootstrap +./configure +scan-build -o "$results_dir" \ + --keep-empty \ + --html-title="OpenSMTPD $sha" make + + +set -x +# conditionally generate badge +if [ -z "${CLANG_SCAN_BADGE_REQUIRED:-}" ]; then + echo "Skipping badge generation" +else + echo "Generating badge" + . ci/scripts/imports/badge.sh + cd "$results_dir" + cd "$( find . -type d | sort | tail -n1 )" + issues_nr="$( find . -name "report-*" | wc -l)" + download_badge "$issues_nr" "clang analysis" "$(pwd)" 30 +fi diff --git a/ci/scripts/coverity_scan.sh b/ci/scripts/coverity_scan.sh new file mode 100755 index 00000000..ab302767 --- /dev/null +++ b/ci/scripts/coverity_scan.sh @@ -0,0 +1,77 @@ +#!/bin/sh +set -eu + +# Coverity Scan script +# Steps closely follow official documentation https://scan.coverity.com/download +# +# USAGE: provide coverity project token as 'token' environment variable and run +# token=abcdedf ./ci/scripts/coverity_scan.sh +# +# Or uncomment this line and put token here. But do not commit this to git. +# token="" +project_name="OpenSMTPD%2FOpenSMTPD" +cov_analysis_url="https://scan.coverity.com/download/cxx/linux64" +maintainer="ihor@antonovs.family" + +# Unconditionally go to the root level of the git repo. +# If you invoke it from outside of the repo go to +# the script location first +cd "$(dirname "$0")" +# This moves us to the root of the repo +cd "$(git rev-parse --show-toplevel)" + +# Get short SHA of the HEAD +sha=$(git rev-parse --short HEAD) + +# Download Coverity Build Tool if absent +set +x +# shellcheck disable=SC2154 +md5sum -c ./ci/COVERITY.MD5SUM || wget $cov_analysis_url \ + --post-data "token=$token&project=$project_name" \ + -O cov-analysis-linux64.tgz +set -x + +#Check MD5 +md5sum -c ./ci/COVERITY.MD5SUM + +# Extract Coverty Scan Tool +rm -rf ./cov-analysis-linux64 +mkdir -p cov-analysis-linux64 +tar xzf cov-analysis-linux64.tgz --strip 1 -C cov-analysis-linux64 + +# export PATH=$(pwd)/cov-analysis-linux64/bin:$PATH + +# Build with cov-build +./bootstrap +./configure +cov-analysis-linux64/bin/cov-build --dir cov-int make + +# Compress the rusults +tar czvf opensmtpd.tgz cov-int + + +# Submit the result to Coverity Scan +# Some parts are shamelessly taken from: +# https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh +set +x +response=$(curl \ + --silent \ + --write-out "\n%{http_code}\n" \ + --form token="$token" \ + --form email="$maintainer" \ + --form file=@opensmtpd.tgz \ + --form version="portable-$sha" \ + --form description="daily scan" \ + "https://scan.coverity.com/builds?project=$project_name") +set -x + +status_code=$(echo "$response" | sed -n '$p') + +if [ "$status_code" != "200" ]; then + text=$(echo "$response" | sed '$d') + echo -e "Coverity Scan upload failed: $text" + exit 1 +fi + + + diff --git a/ci/scripts/generate_certs.sh b/ci/scripts/generate_certs.sh new file mode 100755 index 00000000..a9249c1e --- /dev/null +++ b/ci/scripts/generate_certs.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# Generate self-signed SSL certs +# Usage: ./generate_certs.sh + +days=3560 # 10 years +config="$(dirname "$0")/ssl.conf" +cert="open.smtpd.cert" +key="open.smtpd.key" +csr="open.smtpd.csr" + +# Key + CSR generation: +openssl req \ + -new \ + -x509 \ + -newkey rsa:2048 \ + -sha256 \ + -nodes \ + -keyout $key \ + -out $csr \ + -days $days \ + -config "$config" + +# Certificate generation: +openssl req \ + -new \ + -x509 \ + -newkey rsa:2048 \ + -days $days \ + -nodes \ + -config "$config" \ + -keyout $key \ + -out $cert diff --git a/ci/scripts/imports/badge.sh b/ci/scripts/imports/badge.sh new file mode 100644 index 00000000..d6cf0b3a --- /dev/null +++ b/ci/scripts/imports/badge.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# Copyright 2019 Neovim Project Contributors (https://neovim.io/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Helper functions for getting badges. + +# Get code quality color. +# ${1}: Amount of bugs actually found. +# ${2}: Maximum number of bugs above which color will be red. Defaults to 20. +# ${3}: Maximum number of bugs above which color will be yellow. Defaults to +# $1 / 2. +# Output: 24-bit hexadecimal representation of the color (xxxxxx). +get_code_quality_color() { + bugs=$1 ; shift # shift will fail if there is no argument + max_bugs=${1:-20} + yellow_threshold=${2:-$(( max_bugs / 2 ))} + + red=255 + green=255 + blue=0 + + bugs=$(( bugs < max_bugs ? bugs : max_bugs)) + if test $bugs -ge "$yellow_threshold" ; then + green=$(( 255 - 255 * (bugs - yellow_threshold) / yellow_threshold )) + else + red=$(( 255 * bugs / yellow_threshold )) + fi + + printf "%02x%02x%02x" $red $green $blue +} + +# Get code quality badge. +# ${1}: Amount of bugs actually found. +# ${2}: Badge text. +# ${3}: Directory where to save badge to. +# ${3}: Maximum number of bugs above which color will be red. Defaults to 20. +# ${4}: Maximum number of bugs above which color will be yellow. Defaults to +# $1 / 2. +# Output: 24-bit hexadecimal representation of the color (xxxxxx). +download_badge() { + bugs=$1 ; shift + badge_text="$1" ; shift + reports_dir="$1" ; shift + max_bugs=${1:-20} + yellow_threshold=${2:-$(( max_bugs / 2 ))} + + code_quality_color="$( + get_code_quality_color $bugs $max_bugs $yellow_threshold)" + badge="${badge_text}-${bugs}-${code_quality_color}" + + rm -f "$reports_dir/badge.svg" + + response="$( + curl --tlsv1 "https://img.shields.io/badge/${badge}.svg" \ + -o"$reports_dir/badge.svg" 2>&1)" + + if ! grep -F 'xmlns="http://www.w3.org/2000/svg"' "$reports_dir/badge.svg" ; then + echo "Failed to download badge to $reports_dir: $response" + rm -f "$reports_dir/badge.svg" + fi +} diff --git a/ci/scripts/ssl.conf b/ci/scripts/ssl.conf new file mode 100644 index 00000000..eddfb7f8 --- /dev/null +++ b/ci/scripts/ssl.conf @@ -0,0 +1,23 @@ +[req] +default_bits = 2048 +prompt = no +default_md = sha256 +x509_extensions = v3_req +distinguished_name = dn + + +# Puffy the pufferfish +# https://en.wikipedia.org/wiki/Tetraodontidae +[dn] +C = AZ +ST = Chordata +L = Actinopterygii_Tetraodontiformes +O = Tetraodontoidei_Tetraodontidae +CN = Puffy + +[v3_req] +subjectAltName = @alt_names + +[alt_names] +DNS.1 = puffy.bsd +DNS.2 = puffy.mail |