mirror of
https://github.com/gutmensch/docker-dmarc-report.git
synced 2025-12-18 10:16:34 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78144ee1e4 | ||
|
|
2bd4fa2677 | ||
|
|
5e95ad2e14 | ||
|
|
81cad2e81e | ||
|
|
919fe857ae | ||
|
|
b28ae804bf | ||
|
|
552f67da65 | ||
|
|
072c8e5e33 | ||
|
|
7455b3a4bc | ||
|
|
36b5748844 | ||
|
|
58d3e23ff1 | ||
|
|
07a932ae19 | ||
|
|
e7c55a0d2c | ||
|
|
2bcf0673d2 | ||
|
|
1e7c3d841d | ||
|
|
f8e7050f94 | ||
|
|
8f1fb13960 | ||
|
|
4486d7d8bf | ||
|
|
0cc77fd254 | ||
|
|
73baf6f923 | ||
|
|
8981d3afbf | ||
|
|
aab0d17980 | ||
|
|
07b5a195b4 | ||
|
|
da49afba3d | ||
|
|
19f680a865 | ||
|
|
87e271d084 | ||
|
|
87ee0534df | ||
|
|
b895501242 | ||
|
|
6a21e9efab | ||
|
|
bf2f61f236 | ||
|
|
9637263016 | ||
|
|
b7a924ea5a | ||
|
|
aadc22d760 | ||
|
|
3ff0de46cd | ||
|
|
3da8a5ff63 | ||
|
|
28e21af0f5 | ||
|
|
a5ff675bc9 | ||
|
|
b5271abc8a | ||
|
|
a1358b9187 | ||
|
|
71d487cb9d | ||
|
|
526e230616 | ||
|
|
c74bc90d20 |
35
.github/workflows/contributors.yml
vendored
Normal file
35
.github/workflows/contributors.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: Contributors
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
contributors:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: wow-actions/contributors-list@v1
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
svgPath: CONTRIBUTORS.svg
|
||||||
|
sort: true
|
||||||
|
round: true
|
||||||
|
includeBots: false
|
||||||
|
userNameHeight: 19
|
||||||
|
# This job does not have commit powers to the `master` branch
|
||||||
|
noCommit: true
|
||||||
|
itemTemplate: >
|
||||||
|
<g transform="translate({{ x }}, {{ y }})">
|
||||||
|
<a xlink:href="{{{ url }}}" class="contributor-link" target="_blank" rel="nofollow sponsored" title="{{{ name }}}" id="{{{ name }}}">
|
||||||
|
<image width="{{ width }}" height="{{ height }}" xlink:href="{{{ avatar }}}" />
|
||||||
|
<text x="32" y="74" text-anchor="middle" alignment-baseline="middle" font-size="10">{{{ name }}}</text>
|
||||||
|
</a>
|
||||||
|
</g>
|
||||||
|
- name: Create Pull Request
|
||||||
|
uses: peter-evans/create-pull-request@v3
|
||||||
|
with:
|
||||||
|
commit-message: '[chore] update contributors svg'
|
||||||
|
title: '[chore] update contributors svg'
|
||||||
|
delete-branch: true
|
||||||
|
assignees: gutmensch
|
||||||
|
reviewers: gutmensch
|
||||||
54
.github/workflows/docker-image.yml
vendored
Normal file
54
.github/workflows/docker-image.yml
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
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: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- 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@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64, linux/arm64
|
||||||
|
file: Dockerfile
|
||||||
|
push: ${{ github.ref_type == 'tag' }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.meta.outputs.tags }}
|
||||||
|
gutmensch/dmarc-report:latest
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
63
CONTRIBUTORS.svg
Normal file
63
CONTRIBUTORS.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 3.5 MiB |
74
Dockerfile
74
Dockerfile
@ -1,25 +1,59 @@
|
|||||||
FROM boxedcode/alpine-nginx-php-fpm:v1.7.2
|
ARG UPSTREAM_IMAGE=trafex/php-nginx:2.6.0
|
||||||
|
|
||||||
MAINTAINER Robert Schumann <gutmensch@n-os.org>
|
FROM $UPSTREAM_IMAGE
|
||||||
|
|
||||||
|
LABEL maintainer="Robert Schumann <rs@n-os.org>"
|
||||||
|
|
||||||
ENV REPORT_PARSER_SOURCE="https://github.com/techsneeze/dmarcts-report-parser/archive/master.zip" \
|
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
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
COPY ./manifest/ /
|
COPY ./manifest/ /
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -e -x \
|
||||||
&& apk update \
|
&& apk add -U \
|
||||||
&& apk add expat-dev mariadb-dev gzip \
|
bash \
|
||||||
&& wget -q --no-check-certificate -O parser.zip $REPORT_PARSER_SOURCE \
|
cmake \
|
||||||
&& wget -q --no-check-certificate -O viewer.zip $REPORT_VIEWER_SOURCE \
|
expat-dev \
|
||||||
&& unzip parser.zip && cp -av dmarcts-report-parser-master/* /usr/bin/ && rm -f parser.zip \
|
g++ \
|
||||||
&& unzip viewer.zip && cp -av dmarcts-report-viewer-master/* /var/www/viewer/ && rm -f viewer.zip \
|
gpg \
|
||||||
|
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 "1s/^/body { font-family: Sans-Serif; }\n/" /var/www/viewer/default.css \
|
||||||
&& (echo y;echo o conf prerequisites_policy follow;echo o conf commit)|cpan \
|
&& sed -i 's%.*listen [::]:8080 default_server;% listen [::]:80 default_server;%g' /etc/nginx/nginx.conf \
|
||||||
&& cpan install SULLR/IO-Socket-SSL-2.060.tar.gz \
|
&& sed -i 's%.*listen 8080 default_server;% listen 80 default_server;%g' /etc/nginx/nginx.conf \
|
||||||
&& cpan install MICHIELB/File-MimeInfo-0.28.tar.gz \
|
&& 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 allow_installing_outdated_dists yes;echo o conf prerequisites_policy follow;echo o conf commit)|cpan \
|
||||||
&& for i in \
|
&& for i in \
|
||||||
|
IO::Socket::SSL \
|
||||||
CPAN \
|
CPAN \
|
||||||
|
CPAN::DistnameInfo \
|
||||||
|
File::MimeInfo \
|
||||||
IO::Compress::Gzip \
|
IO::Compress::Gzip \
|
||||||
Getopt::Long \
|
Getopt::Long \
|
||||||
Mail::IMAPClient \
|
Mail::IMAPClient \
|
||||||
@ -31,17 +65,19 @@ RUN set -x \
|
|||||||
XML::Parser \
|
XML::Parser \
|
||||||
XML::Simple \
|
XML::Simple \
|
||||||
DBI \
|
DBI \
|
||||||
DBD::mysql \
|
# XXX: pinning to a version, which does not suffer from mariadb 10 version comparison issues
|
||||||
|
# TODO: replace with DBD::mysql again, when issue is resolved
|
||||||
|
# https://forum.bestpractical.com/t/mysql-dependency-error-with-mariadb-and-debian-12/38748/2
|
||||||
|
DVEEDEN/DBD-mysql-4.052.tar.gz \
|
||||||
|
DBD::Pg \
|
||||||
Socket \
|
Socket \
|
||||||
Socket6 \
|
Socket6 \
|
||||||
PerlIO::gzip \
|
PerlIO::gzip \
|
||||||
; do cpan install $i; done \
|
; do cpan install $i; done \
|
||||||
&& apk del mariadb-dev expat-dev \
|
&& apk del mariadb-dev expat-dev openssl-dev perl-dev g++ cmake make musl-obstack-dev libpq-dev
|
||||||
&& apk add mariadb-client-libs \
|
|
||||||
&& sed -i 's%.*root /var/www/html;% root /var/www/viewer;%g' /etc/nginx/conf.d/default.conf \
|
|
||||||
&& sed -i 's/.*index index.php index.html index.htm;/ index dmarcts-report-viewer.php;/g' /etc/nginx/conf.d/default.conf \
|
|
||||||
&& chmod 755 /entrypoint.sh
|
|
||||||
|
|
||||||
EXPOSE 443 80
|
HEALTHCHECK --interval=1m --timeout=3s CMD curl --silent --fail http://127.0.0.1:80/fpm-ping
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
CMD ["/bin/bash", "/entrypoint.sh"]
|
CMD ["/bin/bash", "/entrypoint.sh"]
|
||||||
|
|||||||
125
Jenkinsfile
vendored
Normal file
125
Jenkinsfile
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
|
|
||||||
|
DOCKER_IMAGE_NAME = ''
|
||||||
|
DOCKER_IMAGE = ''
|
||||||
|
DOCKER_ARGS = '--network=services_default'
|
||||||
|
DOCKER_REGISTRY = 'registry.n-os.org:5000'
|
||||||
|
|
||||||
|
|
||||||
|
properties([
|
||||||
|
disableConcurrentBuilds(),
|
||||||
|
parameters([
|
||||||
|
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: 'Do you want to run the build with tests?')
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
node {
|
||||||
|
try {
|
||||||
|
pipeline()
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
setBuildStatus(e.toString().take(140), 'FAILURE')
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
cleanup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************
|
||||||
|
|
||||||
|
standard functions
|
||||||
|
these functions below implement the standard docker image pipeline
|
||||||
|
|
||||||
|
******************************************************************
|
||||||
|
*/
|
||||||
|
def pipeline() {
|
||||||
|
|
||||||
|
stage('checkout git') {
|
||||||
|
checkout scm
|
||||||
|
setBuildStatus('In progress...', 'PENDING')
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://docs.cloudbees.com/docs/admin-resources/latest/plugins/docker-workflow
|
||||||
|
stage('build image') {
|
||||||
|
DOCKER_IMAGE_NAME = "${DOCKER_REGISTRY}/${getDockerImage()}:${getDockerTag()}"
|
||||||
|
DOCKER_IMAGE = docker.build(DOCKER_IMAGE_NAME, "--no-cache ${DOCKER_ARGS} .")
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('run tests') {
|
||||||
|
if (fileExists('./test/run.sh') && !params.SKIP_TESTS) {
|
||||||
|
DOCKER_IMAGE.inside("${DOCKER_ARGS} --entrypoint=") {
|
||||||
|
sh 'bash /usr/build/test/run.sh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Utils.markStageSkippedForConditional('run tests')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('push image') {
|
||||||
|
if (BRANCH_NAME == 'master') {
|
||||||
|
DOCKER_IMAGE.push()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Utils.markStageSkippedForConditional('push image')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('delete image') {
|
||||||
|
if (BRANCH_NAME == 'master') {
|
||||||
|
Utils.markStageSkippedForConditional('delete image')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deleteDockerImage(DOCKER_IMAGE_NAME)
|
||||||
|
}
|
||||||
|
setBuildStatus('Success', 'SUCCESS')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteDockerImage(image) {
|
||||||
|
sh(script: "docker rmi -f ${image}")
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup() {
|
||||||
|
stage('schedule cleanup') {
|
||||||
|
build job: '/maintenance/starter', wait: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDockerImage() {
|
||||||
|
return sh(script: "echo '${JOB_NAME}' | awk -F/ '{print \$(NF-1)}' | sed 's%docker-%%'", returnStdout: true).trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDockerTag() {
|
||||||
|
def shortHash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
|
||||||
|
def date = new Date()
|
||||||
|
def sdf = new SimpleDateFormat("yyyyMMddHHmmss")
|
||||||
|
// semver in TAG_ID file or reference to ARG in Dockerfile
|
||||||
|
if (!fileExists('./TAG_ID')) {
|
||||||
|
return "${sdf.format(date)}.${shortHash}.b${BUILD_ID}"
|
||||||
|
}
|
||||||
|
def tagId = sh(script: 'cat ./TAG_ID', returnStdout: true).trim()
|
||||||
|
if (tagId ==~ /^[A-Z_]+$/) {
|
||||||
|
return sh(script: "awk -F= '/ARG ${tagId}=/{print \$2}' Dockerfile", returnStdout: true).trim()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return tagId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBuildStatus(message, state) {
|
||||||
|
def repoUrl = sh(script: 'git config --get remote.origin.url', returnStdout: true).trim()
|
||||||
|
step([
|
||||||
|
$class: "GitHubCommitStatusSetter",
|
||||||
|
reposSource: [$class: "ManuallyEnteredRepositorySource", url: repoUrl],
|
||||||
|
contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "ci/jenkins/build-status"],
|
||||||
|
errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
|
||||||
|
statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
|
||||||
|
]);
|
||||||
|
}
|
||||||
93
README.md
93
README.md
@ -1,75 +1,74 @@
|
|||||||
# docker-dmarc-report [](https://registry.hub.docker.com/u/gutmensch/dmarc-report/)
|
# docker-dmarc-report  [](https://registry.hub.docker.com/u/gutmensch/dmarc-report/)
|
||||||
|
|
||||||
This image is intended to combine a dmarc report parser (see https://github.com/techsneeze/dmarcts-report-parser by TechSneeze.com and John Bieling) with a report viewer (see https://github.com/techsneeze/dmarcts-report-viewer/ by the same people) into a runnable docker image / microservice.
|
This image is intended to combine a dmarc report parser (see https://github.com/techsneeze/dmarcts-report-parser by TechSneeze.com and John Bieling) with a report viewer (see https://github.com/techsneeze/dmarcts-report-viewer/ by the same people) into a runnable docker image / microservice.
|
||||||
|
|
||||||
It fetches dmarc report mails regularly from an IMAP server, stores them into a MySQL DB and visualizes them via Webserver/PHP module.
|
It fetches dmarc report mails regularly from an IMAP server, stores them into a MySQL DB and visualizes them via Webserver/PHP module.
|
||||||
|
|
||||||
## Howto
|
## 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
|
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\;"
|
"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
|
1. Create a MySQL Database and a user for this service
|
||||||
4. Access port 80 on the container (or 443) or put it behind a reverse proxy to view reports
|
|
||||||
```
|
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 pull gutmensch/dmarc-report
|
||||||
docker run -e ... -ti 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.
|
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
|
## Versions for last build latest and docker image tag 1.4
|
||||||
dmarcts report viewer: 2020-09-06
|
|
||||||
|
|
||||||
dmarcts report parser: 2020-09-06
|
dmarcts report viewer: 2024-02-04
|
||||||
|
|
||||||
|
dmarcts report parser: 2024-02-04
|
||||||
|
|
||||||
|
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
|
## Frontend Screenshot
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Sample docker compose / Environment variables
|
## 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**
|
Make sure to create the IMAP-Folders for processed and error reports before the cron job runs!
|
||||||
```yaml
|
|
||||||
version: '3.6'
|
|
||||||
|
|
||||||
services:
|
The default foldernames are are [`error`](examples/env.example) & [`processed`](examples/env.example) but they can be changed within the [`env-file`](examples/env.example).
|
||||||
dmarc-report:
|
|
||||||
image: "gutmensch/dmarc-report:latest"
|
|
||||||
hostname: dmarc-report
|
|
||||||
container_name: dmarc-report
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
environment:
|
|
||||||
- "REPORT_DB_HOST=db"
|
|
||||||
- "REPORT_DB_NAME=dmarc_report"
|
|
||||||
- "REPORT_DB_USER=dmarc_report"
|
|
||||||
- "REPORT_DB_PASS=dbpassword"
|
|
||||||
- "PARSER_IMAP_SERVER=mail"
|
|
||||||
- "PARSER_IMAP_PORT=143"
|
|
||||||
- "PARSER_IMAP_USER=foobar@example.com"
|
|
||||||
- "PARSER_IMAP_PASS=foobar"
|
|
||||||
- "PARSER_IMAP_READ_FOLDER=Inbox"
|
|
||||||
- "PARSER_IMAP_MOVE_FOLDER=processed"
|
|
||||||
- "PARSER_IMAP_MOVE_FOLDER_ERR=error"
|
|
||||||
|
|
||||||
db:
|
Make sure to rename the [`env.example`](examples/env.example) file to `.env` and adjust the values to your needs.
|
||||||
image: mariadb:10
|
|
||||||
environment:
|
You can find templates for both, [`postgreql`](examples/docker-compose.postgres.yml)
|
||||||
- "MYSQL_ROOT_PASSWORD=dbrootpassword"
|
and [`mysql`](examples/docker-compose.mysql.yml)
|
||||||
- "MYSQL_DATABASE=dmarc_report"
|
db in the [`examples`](examples) directory. Just rename the setup you want to use to `docker-compose.yml`.
|
||||||
- "MYSQL_USER=dmarc_report"
|
|
||||||
- "MYSQL_PASSWORD=dbpassword"
|
|
||||||
|
|
||||||
|
|
||||||
|
## Manual update
|
||||||
|
|
||||||
|
If you are using the docker-compose file above, you can use this command to trigger an manual update. It will fetch the latest reports and parse them.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose exec dmarc-report /usr/bin/dmarcts-report-parser.pl -i -d -r=1
|
||||||
```
|
```
|
||||||
|
|
||||||
## Optional extended configuration
|
## 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"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
For further optional configuration see the docker-compose [`env-file`](examples/env.example).
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
<img src="./CONTRIBUTORS.svg">
|
||||||
|
|
||||||
|
## Stargazers over time
|
||||||
|
|
||||||
|
[](https://starchart.cc/gutmensch/docker-dmarc-report)
|
||||||
|
|||||||
46
examples/docker-compose.mysql.yml
Normal file
46
examples/docker-compose.mysql.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
services:
|
||||||
|
dmarc-report:
|
||||||
|
image: "gutmensch/dmarc-report:latest"
|
||||||
|
hostname: dmarc-report
|
||||||
|
container_name: dmarc-report
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
environment:
|
||||||
|
- "REPORT_DB_HOST=${DB_HOST:-db}"
|
||||||
|
- "REPORT_DB_TYPE=${DB_TYPE:-mysql}"
|
||||||
|
- "REPORT_DB_PORT=${DB_PORT:-3306}"
|
||||||
|
- "REPORT_DB_NAME=${DB_NAME:-dmarc_report}"
|
||||||
|
- "REPORT_DB_USER=${DB_USER:-dmarc_report}"
|
||||||
|
- "REPORT_DB_PASS=${DB_PASSWORD}"
|
||||||
|
- "PARSER_IMAP_SERVER=${IMAP_SERVER}"
|
||||||
|
- "PARSER_IMAP_PORT=${IMAP_PORT:-993}"
|
||||||
|
- "PARSER_IMAP_USER=${IMAP_USER}"
|
||||||
|
- "PARSER_IMAP_PASS=${IMAP_PASSWORD}"
|
||||||
|
- "PARSER_IMAP_READ_FOLDER=${IMAP_READ_FOLDER:-Inbox}"
|
||||||
|
- "PARSER_IMAP_MOVE_FOLDER=${IMAP_MOVE_FOLDER:-processed}"
|
||||||
|
- "PARSER_IMAP_MOVE_FOLDER_ERR=${IMAP_MOVE_FOLDER_ERR:-error}"
|
||||||
|
- "PARSER_IMAP_SSL=${PARSER_IMAP_SSL}"
|
||||||
|
- "PARSER_IMAP_TLS=${PARSER_IMAP_TLS}"
|
||||||
|
- "PARSER_IMAP_IGNORE_ERROR=${PARSER_IMAP_IGNORE_ERROR}"
|
||||||
|
- "PARSER_XML_MAXSIZE=${PARSER_XML_MAXSIZE}"
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: mariadb:10
|
||||||
|
command: --skip-innodb-read-only-compressed
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- "MYSQL_ROOT_PASSWORD=${ROOT_DB_PASSWORD}"
|
||||||
|
- "MYSQL_DATABASE=${DB_NAME:-dmarc_report}"
|
||||||
|
- "MYSQL_USER=${DB_USER:-dmarc_report}"
|
||||||
|
- "MYSQL_PASSWORD=${DB_PASSWORD}"
|
||||||
|
volumes:
|
||||||
|
- ./run/db:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p${ROOT_DB_PASSWORD}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
44
examples/docker-compose.postgres.yml
Normal file
44
examples/docker-compose.postgres.yml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
services:
|
||||||
|
dmarc-report:
|
||||||
|
image: "gutmensch/dmarc-report:latest"
|
||||||
|
hostname: dmarc-report
|
||||||
|
container_name: dmarc-report
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
environment:
|
||||||
|
- "REPORT_DB_HOST=${DB_HOST:-db}"
|
||||||
|
- "REPORT_DB_TYPE=${DB_TYPE:-pgsql}"
|
||||||
|
- "REPORT_DB_PORT=${DB_PORT:-5432}"
|
||||||
|
- "REPORT_DB_NAME=${DB_NAME:-dmarc_report}"
|
||||||
|
- "REPORT_DB_USER=${DB_USER:-dmarc_report}"
|
||||||
|
- "REPORT_DB_PASS=${DB_PASSWORD}"
|
||||||
|
- "PARSER_IMAP_SERVER=${IMAP_SERVER}"
|
||||||
|
- "PARSER_IMAP_PORT=${IMAP_PORT:-993}"
|
||||||
|
- "PARSER_IMAP_USER=${IMAP_USER}"
|
||||||
|
- "PARSER_IMAP_PASS=${IMAP_PASSWORD}"
|
||||||
|
- "PARSER_IMAP_READ_FOLDER=${IMAP_READ_FOLDER:-Inbox}"
|
||||||
|
- "PARSER_IMAP_MOVE_FOLDER=${IMAP_MOVE_FOLDER:-processed}"
|
||||||
|
- "PARSER_IMAP_MOVE_FOLDER_ERR=${IMAP_MOVE_FOLDER_ERR:-error}"
|
||||||
|
- "PARSER_IMAP_SSL=${PARSER_IMAP_SSL}"
|
||||||
|
- "PARSER_IMAP_TLS=${PARSER_IMAP_TLS}"
|
||||||
|
- "PARSER_IMAP_IGNORE_ERROR=${PARSER_IMAP_IGNORE_ERROR}"
|
||||||
|
- "PARSER_XML_MAXSIZE=${PARSER_XML_MAXSIZE}"
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:latest
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- "POSTGRES_DB=${DB_NAME:-dmarc_report}"
|
||||||
|
- "POSTGRES_USER=${DB_USER:-dmarc_report}"
|
||||||
|
- "POSTGRES_PASSWORD=${DB_PASSWORD}"
|
||||||
|
volumes:
|
||||||
|
- ./run/db:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U dmarc_report"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
53
examples/env.example
Normal file
53
examples/env.example
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# database host address, leave empty for default host "db"
|
||||||
|
DB_HOST=
|
||||||
|
|
||||||
|
# the database type mysql or pgsql, leave empty for default (depending on your docker-compose.yml)
|
||||||
|
DB_TYPE=
|
||||||
|
|
||||||
|
# the database port (mysql 3306) (pqsql 5432), leave empty for default (depending on your docker-compose.yml)
|
||||||
|
DB_PORT=
|
||||||
|
|
||||||
|
# the database name, leave empty for default "dmarc_report"
|
||||||
|
DB_NAME=
|
||||||
|
|
||||||
|
# the database name, leave empty for default "dmarc_report"
|
||||||
|
DB_USER=
|
||||||
|
|
||||||
|
# mysql root password. Irrelevant if you are using postgres
|
||||||
|
ROOT_DB_PASSWORD=
|
||||||
|
|
||||||
|
# database password for the database user
|
||||||
|
DB_PASSWORD=
|
||||||
|
|
||||||
|
# the email address receiving the DMARC reports
|
||||||
|
IMAP_USER=
|
||||||
|
|
||||||
|
# the password for the email address receiving the DMARC reports
|
||||||
|
IMAP_PASSWORD=
|
||||||
|
|
||||||
|
# the server the email address is hosted on
|
||||||
|
IMAP_SERVER=
|
||||||
|
|
||||||
|
# optional: default is 993 (or 143)
|
||||||
|
IMAP_PORT=
|
||||||
|
|
||||||
|
# optional: default is "Inbox"
|
||||||
|
IMAP_READ_FOLDER=
|
||||||
|
|
||||||
|
# optional: default is "processed"
|
||||||
|
IMAP_MOVE_FOLDER=
|
||||||
|
|
||||||
|
# optional: default is "error"
|
||||||
|
IMAP_MOVE_FOLDER_ERR=
|
||||||
|
|
||||||
|
# Enable SSL and/or (START-)TLS. Set both to 0 to disable encryption (not recommended)
|
||||||
|
PARSER_IMAP_SSL=0
|
||||||
|
PARSER_IMAP_TLS=1
|
||||||
|
|
||||||
|
# Ignore ERROR: message_string() issue experienced with Exchange Online. Set to 1 to enable
|
||||||
|
PARSER_IMAP_IGNORE_ERROR=0
|
||||||
|
|
||||||
|
# Increase the maximum size of the XML file. (default is 50000 bytes)
|
||||||
|
# When the size exceeds the maximum, one could experience an error Uncaught ValueError: DOMDocument::loadXML():
|
||||||
|
# Argument #1 ($source) must not be empty.
|
||||||
|
PARSER_XML_MAXSIZE=50000
|
||||||
30
manifest/entrypoint.sh
Normal file → Executable file
30
manifest/entrypoint.sh
Normal file → Executable file
@ -1,14 +1,17 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# change according to alpine and php release
|
||||||
|
PHP_VERSION=81
|
||||||
|
|
||||||
# Display PHP error's or not
|
# Display PHP error's or not
|
||||||
if [[ "$ERRORS" != "1" ]] ; then
|
if [[ "$ERRORS" != "1" ]] ; then
|
||||||
sed -i -e "s/error_reporting =.*=/error_reporting = E_ALL/g" /usr/etc/php.ini
|
sed -i -e "s/error_reporting =.*/error_reporting = E_ALL/g" /etc/php${PHP_VERSION}/php.ini
|
||||||
sed -i -e "s/display_errors =.*/display_errors = stdout/g" /usr/etc/php.ini
|
sed -i -e "s/display_errors =.*/display_errors = stdout/g" /etc/php${PHP_VERSION}/php.ini
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Disable opcache?
|
# Disable opcache?
|
||||||
if [[ -v NO_OPCACHE ]]; then
|
if [[ -v NO_OPCACHE ]]; then
|
||||||
sed -i -e "s/zend_extension=opcache.so/;zend_extension=opcache.so/g" /etc/php.d/zend-opcache.ini
|
sed -i -e "s/zend_extension=opcache.so/;zend_extension=opcache.so/g" /etc/php${PHP_VERSION}/conf.d/00_opcache.ini
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Tweak nginx to match the workers to cpu's
|
# Tweak nginx to match the workers to cpu's
|
||||||
@ -16,9 +19,26 @@ procs=$(cat /proc/cpuinfo | grep processor | wc -l)
|
|||||||
sed -i -e "s/worker_processes 5/worker_processes $procs/" /etc/nginx/nginx.conf
|
sed -i -e "s/worker_processes 5/worker_processes $procs/" /etc/nginx/nginx.conf
|
||||||
|
|
||||||
# Copy important env vars for PHP-FPM to access
|
# Copy important env vars for PHP-FPM to access
|
||||||
PHP_ENV_FILE="/usr/etc/php-fpm.d/${PHP_ENV_FILE:-env.conf}"
|
PHP_ENV_FILE="/etc/php${PHP_VERSION}/php-fpm.d/${PHP_ENV_FILE:-env.conf}"
|
||||||
echo '[www]' > "$PHP_ENV_FILE"
|
echo '[www]' > "$PHP_ENV_FILE"
|
||||||
env | grep -e 'REPORT_DB_HOST' -e 'REPORT_DB_NAME' -e 'REPORT_DB_USER' -e 'REPORT_DB_PASS' | sed "s/\(.*\)=\(.*\)/env[\1]='\2'/" >> "$PHP_ENV_FILE"
|
echo 'user = nginx' >> "$PHP_ENV_FILE"
|
||||||
|
echo 'group = www-data' >> "$PHP_ENV_FILE"
|
||||||
|
echo 'listen.owner = nginx' >> "$PHP_ENV_FILE"
|
||||||
|
echo 'listen.group = www-data' >> "$PHP_ENV_FILE"
|
||||||
|
env | grep -e 'REPORT_DB_TYPE' -e 'REPORT_DB_HOST' -e 'REPORT_DB_PORT' -e 'REPORT_DB_NAME' -e 'REPORT_DB_USER' -e 'REPORT_DB_PASS' | sed "s/\(.*\)=\(.*\)/env[\1] = '\2'/" >> "$PHP_ENV_FILE"
|
||||||
|
|
||||||
|
# compat from older image where variable was not existing
|
||||||
|
grep -e ^REPORT_DB_PORT "$PHP_ENV_FILE" || echo env[REPORT_DB_PORT] = 3306 >> "$PHP_ENV_FILE"
|
||||||
|
|
||||||
|
# Get and parse dmarc reports once at startup to avoid PHP errors with a new database
|
||||||
|
if /usr/bin/dmarcts-report-parser.pl -i -d -r > /var/log/nginx/dmarc-reports.log 2>&1; then
|
||||||
|
echo 'INFO: Dmarc reports parsed successfully'
|
||||||
|
else
|
||||||
|
echo 'CRIT: Dmarc reports could not be parsed. Check your IMAP and MYSQL Settings.'
|
||||||
|
echo -e "DEBUG: Parsing failed with the following output:\n"
|
||||||
|
cat /var/log/nginx/dmarc-reports.log
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Start supervisord and services
|
# Start supervisord and services
|
||||||
/usr/bin/supervisord -n -c /etc/supervisord.conf
|
/usr/bin/supervisord -n -c /etc/supervisord.conf
|
||||||
|
|||||||
@ -5,13 +5,15 @@
|
|||||||
# If IMAP access is not used, config options starting with $imap do not need to
|
# If IMAP access is not used, config options starting with $imap do not need to
|
||||||
# be set and are ignored.
|
# be set and are ignored.
|
||||||
|
|
||||||
$debug = 0;
|
$debug = $ENV{'PARSER_DEBUG'} // 0;
|
||||||
$delete_reports = 0;
|
$delete_reports = $ENV{'PARSER_DELETE_REPORTS'} // 0;
|
||||||
|
|
||||||
$dbname = $ENV{'REPORT_DB_NAME'};
|
$dbname = $ENV{'REPORT_DB_NAME'};
|
||||||
$dbuser = $ENV{'REPORT_DB_USER'};
|
$dbuser = $ENV{'REPORT_DB_USER'};
|
||||||
$dbpass = $ENV{'REPORT_DB_PASS'};
|
$dbpass = $ENV{'REPORT_DB_PASS'};
|
||||||
$dbhost = $ENV{'REPORT_DB_HOST'}; # Set the hostname if we can't connect to the local socket.
|
$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'} eq 'pgsql' ? 'Pg' : 'mysql';
|
||||||
|
|
||||||
if(exists $ENV{PARSER_IMAP_SERVER_WITH_PORT} && defined $ENV{PARSER_IMAP_SERVER_WITH_PORT}) {
|
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};
|
my @server_attr = split ':', $ENV{PARSER_IMAP_SERVER_WITH_PORT};
|
||||||
@ -27,7 +29,7 @@ $imappass = $ENV{'PARSER_IMAP_PASS'};
|
|||||||
$imapssl = $ENV{'PARSER_IMAP_SSL'} // '0'; # If set to 1, remember to change server port to 993 and disable imaptls.
|
$imapssl = $ENV{'PARSER_IMAP_SSL'} // '0'; # If set to 1, remember to change server port to 993 and disable imaptls.
|
||||||
$imaptls = $ENV{'PARSER_IMAP_TLS'} // '1'; # Enabled as the default and best-practice.
|
$imaptls = $ENV{'PARSER_IMAP_TLS'} // '1'; # Enabled as the default and best-practice.
|
||||||
$tlsverify = $ENV{'PARSER_IMAP_VERIFY'} // '0'; # Enable verify server cert as the default and best-practice.
|
$tlsverify = $ENV{'PARSER_IMAP_VERIFY'} // '0'; # Enable verify server cert as the default and best-practice.
|
||||||
$imapignoreerror = 0; # set it to 1 if you see an "ERROR: message_string()
|
$imapignoreerror = $ENV{'PARSER_IMAP_IGNORE_ERROR'} // '0';# set it to 1 if you see an "ERROR: message_string()
|
||||||
# expected 119613 bytes but received 81873 you may
|
# expected 119613 bytes but received 81873 you may
|
||||||
# need the IgnoreSizeErrors option" because of malfunction
|
# need the IgnoreSizeErrors option" because of malfunction
|
||||||
# imap server as MS Exchange 2007, ...
|
# imap server as MS Exchange 2007, ...
|
||||||
@ -39,12 +41,12 @@ $imapmovefolder = $ENV{'PARSER_IMAP_MOVE_FOLDER'};
|
|||||||
$imapmovefoldererr = $ENV{'PARSER_IMAP_MOVE_FOLDER_ERR'};
|
$imapmovefoldererr = $ENV{'PARSER_IMAP_MOVE_FOLDER_ERR'};
|
||||||
|
|
||||||
# maximum size of XML files to store in database, long files can cause transaction aborts
|
# 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)
|
# 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,
|
# 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
|
# 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,
|
# delete_reports is set (or --delete is given). Deletion can be enforced by delete_failed,
|
||||||
# however not for database errors.
|
# however not for database errors.
|
||||||
$delete_failed = 0;
|
$delete_failed = $ENV{'PARSER_DELETE_FAILED'} // 0;
|
||||||
|
|||||||
@ -4,11 +4,12 @@
|
|||||||
// ### configuration ##################################################
|
// ### configuration ##################################################
|
||||||
// ####################################################################
|
// ####################################################################
|
||||||
|
|
||||||
|
$dbtype=getenv('REPORT_DB_TYPE');
|
||||||
$dbhost=getenv('REPORT_DB_HOST');
|
$dbhost=getenv('REPORT_DB_HOST');
|
||||||
|
$dbport=getenv('REPORT_DB_PORT');
|
||||||
$dbname=getenv('REPORT_DB_NAME');
|
$dbname=getenv('REPORT_DB_NAME');
|
||||||
$dbuser=getenv('REPORT_DB_USER');
|
$dbuser=getenv('REPORT_DB_USER');
|
||||||
$dbpass=getenv('REPORT_DB_PASS');
|
$dbpass=getenv('REPORT_DB_PASS');
|
||||||
$dbport='3306';
|
|
||||||
|
|
||||||
$cssfile="default.css";
|
$cssfile="default.css";
|
||||||
|
|
||||||
|
|||||||
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
|
Before Width: | Height: | Size: 571 KiB After Width: | Height: | Size: 568 KiB |
Loading…
x
Reference in New Issue
Block a user