From 8981d3afbfec92621fa1cc2805bfa7525bfe557f Mon Sep 17 00:00:00 2001 From: Robert Schumann Date: Sat, 7 Jan 2023 23:04:11 +0100 Subject: [PATCH] chore(build): add github action * update documentation * fix report parser option and defaults * fixes #28 * fixes #31 --- .github/workflows/docker-image.yml | 45 ++++++++ Dockerfile | 114 ++++++++++---------- README.md | 55 ++++++---- manifest/usr/bin/dmarcts-report-parser.conf | 10 +- 4 files changed, 142 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..cac8997 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,45 @@ +name: Docker Image CI + +on: + push: + branches: + - master + tags: + - "v*" + pull_request: + branches: + - master + +jobs: + build-and-release: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: gutmensch/dmarc-report + flavor: latest=true + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + + - name: Login to DockerHub + if: github.ref_type == 'tag' + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: . + file: Dockerfile + push: ${{ github.ref_type == 'tag' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index 4721bb2..ad34d1f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ FROM $UPSTREAM_IMAGE LABEL maintainer="Robert Schumann " ENV REPORT_PARSER_SOURCE="https://github.com/techsneeze/dmarcts-report-parser/archive/master.zip" \ - REPORT_VIEWER_SOURCE="https://github.com/techsneeze/dmarcts-report-viewer/archive/master.zip" + REPORT_VIEWER_SOURCE="https://github.com/techsneeze/dmarcts-report-viewer/archive/master.zip" USER root @@ -14,62 +14,62 @@ WORKDIR / COPY ./manifest/ / RUN set -x \ - && apk add -U \ - bash \ - expat-dev \ - g++ \ - gzip \ - libpq \ - libpq-dev \ - make \ - mariadb-client \ - mariadb-connector-c \ - mariadb-dev \ - musl-obstack \ - musl-obstack-dev \ - openssl \ - openssl-dev \ - perl-dev \ - perl-utils \ - php81-pdo \ - php81-pdo_mysql \ - php81-pdo_pgsql \ - tzdata \ - wget \ - && wget -4 -q --no-check-certificate -O parser.zip $REPORT_PARSER_SOURCE \ - && wget -4 -q --no-check-certificate -O viewer.zip $REPORT_VIEWER_SOURCE \ - && unzip parser.zip && cp -av dmarcts-report-parser-master/* /usr/bin/ && rm -vf parser.zip && rm -rvf dmarcts-report-parser-master \ - && unzip viewer.zip && cp -av dmarcts-report-viewer-master/* /var/www/viewer/ && rm -vf viewer.zip && rm -rvf dmarcts-report-viewer-master \ - && sed -i "1s/^/body { font-family: Sans-Serif; }\n/" /var/www/viewer/default.css \ - && sed -i 's%.*listen [::]:8080 default_server;% listen [::]:80 default_server;%g' /etc/nginx/nginx.conf \ - && sed -i 's%.*listen 8080 default_server;% listen 80 default_server;%g' /etc/nginx/nginx.conf \ - && sed -i 's%.*root /var/www/html;% root /var/www/viewer;%g' /etc/nginx/nginx.conf \ - && sed -i 's/.*index index.php index.html;/ index dmarcts-report-viewer.php;/g' /etc/nginx/nginx.conf \ - && sed -i 's%files = /etc/supervisor.d/\*.ini%files = /etc/supervisor/conf.d/*.conf%g' /etc/supervisord.conf \ - && (echo y;echo o conf prerequisites_policy follow;echo o conf commit)|cpan \ - && for i in \ - IO::Socket::SSL \ - CPAN \ - CPAN::DistnameInfo \ - File::MimeInfo \ - IO::Compress::Gzip \ - Getopt::Long \ - Mail::IMAPClient \ - Mail::Mbox::MessageParser \ - MIME::Base64 \ - MIME::Words \ - MIME::Parser \ - MIME::Parser::Filer \ - XML::Parser \ - XML::Simple \ - DBI \ - DBD::mysql \ - DBD::Pg \ - Socket \ - Socket6 \ - PerlIO::gzip \ - ; do cpan install $i; done \ - && apk del mariadb-dev expat-dev openssl-dev perl-dev g++ make musl-obstack-dev libpq-dev + && apk add -U \ + bash \ + expat-dev \ + g++ \ + gzip \ + libpq \ + libpq-dev \ + make \ + mariadb-client \ + mariadb-connector-c \ + mariadb-dev \ + musl-obstack \ + musl-obstack-dev \ + openssl \ + openssl-dev \ + perl-dev \ + perl-utils \ + php81-pdo \ + php81-pdo_mysql \ + php81-pdo_pgsql \ + tzdata \ + wget \ + && wget -4 -q --no-check-certificate -O parser.zip $REPORT_PARSER_SOURCE \ + && wget -4 -q --no-check-certificate -O viewer.zip $REPORT_VIEWER_SOURCE \ + && unzip parser.zip && cp -av dmarcts-report-parser-master/* /usr/bin/ && rm -vf parser.zip && rm -rvf dmarcts-report-parser-master \ + && unzip viewer.zip && cp -av dmarcts-report-viewer-master/* /var/www/viewer/ && rm -vf viewer.zip && rm -rvf dmarcts-report-viewer-master \ + && sed -i "1s/^/body { font-family: Sans-Serif; }\n/" /var/www/viewer/default.css \ + && sed -i 's%.*listen [::]:8080 default_server;% listen [::]:80 default_server;%g' /etc/nginx/nginx.conf \ + && sed -i 's%.*listen 8080 default_server;% listen 80 default_server;%g' /etc/nginx/nginx.conf \ + && sed -i 's%.*root /var/www/html;% root /var/www/viewer;%g' /etc/nginx/nginx.conf \ + && sed -i 's/.*index index.php index.html;/ index dmarcts-report-viewer.php;/g' /etc/nginx/nginx.conf \ + && sed -i 's%files = /etc/supervisor.d/\*.ini%files = /etc/supervisor/conf.d/*.conf%g' /etc/supervisord.conf \ + && (echo y;echo o conf prerequisites_policy follow;echo o conf commit)|cpan \ + && for i in \ + IO::Socket::SSL \ + CPAN \ + CPAN::DistnameInfo \ + File::MimeInfo \ + IO::Compress::Gzip \ + Getopt::Long \ + Mail::IMAPClient \ + Mail::Mbox::MessageParser \ + MIME::Base64 \ + MIME::Words \ + MIME::Parser \ + MIME::Parser::Filer \ + XML::Parser \ + XML::Simple \ + DBI \ + DBD::mysql \ + DBD::Pg \ + Socket \ + Socket6 \ + PerlIO::gzip \ + ; do cpan install $i; done \ + && apk del mariadb-dev expat-dev openssl-dev perl-dev g++ make musl-obstack-dev libpq-dev HEALTHCHECK --interval=1m --timeout=3s CMD curl --silent --fail http://127.0.0.1:80/fpm-ping diff --git a/README.md b/README.md index fe666b3..3268f30 100644 --- a/README.md +++ b/README.md @@ -5,37 +5,47 @@ This image is intended to combine a dmarc report parser (see https://github.com/ It fetches dmarc report mails regularly from an IMAP server, stores them into a MySQL DB and visualizes them via Webserver/PHP module. ## Howto -1. Create a _dmarc.example.com TXT DNS record for your domain, containg an IMAP postbox, e.g. -``` + +1. Create a \_dmarc.example.com TXT DNS record for your domain, containg an IMAP postbox, e.g. + +```bash 17:18 $ dig TXT _dmarc.schumann.link +short "v=DMARC1\; p=quarantine\; fo=1\; rua=mailto:dmarc@schumann.link\; ruf=mailto:dmarc@schumann.link\; adkim=s\; aspf=s\;" ``` -2. Create a MySQL Database and a user for this service -3. Run this docker image with below mentioned env vars -4. Access port 80 on the container (or 443) or put it behind a reverse proxy to view reports -``` + +1. Create a MySQL Database and a user for this service + +1. Run this docker image with below mentioned env vars + +1. Access port 80 on the container (or 443) or put it behind a reverse proxy to view reports + +```bash docker pull gutmensch/dmarc-report docker run -e ... -ti gutmensch/dmarc-report ``` New dmarc reports will be fetched every 15 minutes past the hour, every hour. Therefore it can take up to one hour for the first report to be fetched. -## Versions for last build latest and docker image tag 1.3 -dmarcts report viewer: 2022-08-10 +## Versions for last build latest and docker image tag 1.4 -dmarcts report parser: 2022-08-10 +dmarcts report viewer: 2023-01-07 + +dmarcts report parser: 2023-01-07 CAUTION: The old gutmensch/dmarc-report:latest image (older alpine, php5, etc.) is available still as gutmensch/dmarc-report:0.5. The current latest (and 1.0) uses the latest alpine version, newer MySQL client libraries, newer OpenSSL, etc. and improves compatibilitiy with MySQL 8+. ## Frontend Screenshot + ![DMARC Report Viewer](https://github.com/gutmensch/docker-dmarc-report/blob/master/screenshot.png?raw=true) ## Sample docker compose / Environment variables + The variables should be self-explanatory. Make sure to create the IMAP folders before the cron job runs! **docker-compose.yml** + ```yaml -version: '3.6' +version: "3.6" services: dmarc-report: @@ -71,17 +81,22 @@ services: ``` ## Optional extended configuration + Use SSL instead of default TLS. Set both to 0 to turn off encryption. (not recommended) + ```yaml - - "PARSER_IMAP_SSL=1" - - "PARSER_IMAP_TLS=0" -``` -Ignore ERROR: message_string() issue experienced with Exchange Online. -```yaml - - "PARSER_IMAP_IGNORE_ERROR=1" -``` -Parser and Viewer support Postgres now too (default is mysql) -```yaml - - "REPORT_DB_TYPE=pgsql" +- "PARSER_IMAP_SSL=1" +- "PARSER_IMAP_TLS=0" ``` +Ignore ERROR: message_string() issue experienced with Exchange Online. + +```yaml +- "PARSER_IMAP_IGNORE_ERROR=1" +``` + +Parser and Viewer support Postgres now too (default is mysql) + +```yaml +- "REPORT_DB_TYPE=Pg" +``` diff --git a/manifest/usr/bin/dmarcts-report-parser.conf b/manifest/usr/bin/dmarcts-report-parser.conf index 12bd5de..f6f1b29 100644 --- a/manifest/usr/bin/dmarcts-report-parser.conf +++ b/manifest/usr/bin/dmarcts-report-parser.conf @@ -12,8 +12,8 @@ $dbname = $ENV{'REPORT_DB_NAME'}; $dbuser = $ENV{'REPORT_DB_USER'}; $dbpass = $ENV{'REPORT_DB_PASS'}; $dbhost = $ENV{'REPORT_DB_HOST'}; # Set the hostname if we can't connect to the local socket. -$dbport = $ENV{'REPORT_DB_PORT'} || 3306; -$dbtype = $ENV{'REPORT_DB_TYPE'} || 'mysql'; +$dbport = $ENV{'REPORT_DB_PORT'} // 3306; +$dbtype = $ENV{'REPORT_DB_TYPE'} // 'mysql'; if(exists $ENV{PARSER_IMAP_SERVER_WITH_PORT} && defined $ENV{PARSER_IMAP_SERVER_WITH_PORT}) { my @server_attr = split ':', $ENV{PARSER_IMAP_SERVER_WITH_PORT}; @@ -41,12 +41,12 @@ $imapmovefolder = $ENV{'PARSER_IMAP_MOVE_FOLDER'}; $imapmovefoldererr = $ENV{'PARSER_IMAP_MOVE_FOLDER_ERR'}; # maximum size of XML files to store in database, long files can cause transaction aborts -$maxsize_xml = 50000; +$maxsize_xml = $ENV{'PARSER_XML_MAXSIZE'} // 50000; # store XML as base64 encopded gzip in database (save space, harder usable) -$compress_xml = 0; +$compress_xml = $ENV{'PARSER_XML_COMPRESS'} // 0; # if there was an error during file processing (message does not contain XML or ZIP parts, # or a database error) the parser reports an error and does not delete the file, even if # delete_reports is set (or --delete is given). Deletion can be enforced by delete_failed, # however not for database errors. -$delete_failed = 0; +$delete_failed = $ENV{'PARSER_DELETE_FAILED'} // 0;