Reaction-Mailcreate
This script is used to send a challenge mail to the participating sites.
To do this, the script takes a mail template and a list of participating sites as file input and an identifier for the run as command-line argument, generates a mail for each site, saves the mail for reference, sends it, and calls a URL on the target webserver to "arm" the challenge for the site.
The exact behavior can be fine-tuned with lots of parameters. The
parameters can be queried with the -h/--help
option, like this:
./createMails.py --help
All options are briefly described, and the default values are given.
If not all necessary options are passed on the command line, the script reverts to "dry-run mode," which means it only generates and stores the e-mail files, but does not send them or interact with the target webserver.
Input Formats
The script takes two files as input, namely (by default):
-
{basedir}/{campaign}/Mail.template
, the mail template file, and -
{basedir}/{campaign}/Input{infix}.lst
, the list of participating sites. (Thebasedir
variable is set toMails
by default, while thecampaign
variable is set toTest
by default.)
In addition, an infix
can to be specified on the command line as a
positional parameter. The idea is that this allows separate runs of the
comms challenge to be clearly separated in the file names as well. The
default is empty.
Mail Template
The mail template is expected to be in Jinja2 format. It can be as simple (and functionally useless for a comms challenge) as
Hello there,
this is a trivial mail.
Yours,
The Sender.
but a reasonable example would be
Dear security contact for {{site}},
you have received this message to verify the security contact data set in
the eduGAIN Database for your Identity Federation.
Please confirm that this contact is still correct by clicking the following
URL and following the instructions:
{{URL}}
No further action is required except for the above.
Sincerely yours,
the eduGAIN Security Team.
A lot of variables are passed to Jinja2, in particular
-
site
, -
firstname
, -
lastname
, -
email
, -
URL
, among other variables. The first four variables are taken straight from the input file, while theURL
variable is generated according to the command-line parameters (or defaults).
Participant List
The list of participating sites is expected to be a CSV file with four
columns: site
,firstname
, lastname
, and email
, in that order (and
with the column titles in the first row).
site
, firstname
and lastname
may be empty (though the site
value is
used to separate the mail files into directories by default, so if this
should be empty, the output
option must be set to something that does not
include site
). So, an example for a valid site input file (containing
only one participating site) would be
site,firstname,lastname,email
DFN-CERT,Tobias,Dussa,dussa@dfn-cert.de
Parameters
General Parameters
-
-b
/--basedir
: The base directory for all the input/output data. Defaults toMails
. -
-c
/--campaign
: The campaign identifier. Defaults toTest
. -
-d
/--dry-run
: Toggle to force dry-run mode (no mails are actually sent, no web calls are actually made). Useful to test whether the input data and the mail template used actually generate sensible mails. -
-h
/--help
: Displays the help text and exits the script. -
-i
/--input
: The input file for the participating sites. Defaults to{basedir}/{campaign}/Input{infix}.lst
. -
-I
/--message-id
: Create a message ID. Useful when the mail server used is not standard-compliant and does not add one like it is supposed to do. -
-o
/--output
: The output file name template to be used when generating the mail files. Defaults to{basedir}/{campaign}/{site}/{timestamp}{infix}.eml
. -
-t
/--template
: The mail template file to be used. Defaults to{basedir}/{campaign}/Mail.template
. -
--timestamp
: The format used for thetimestamp
variable. Defaults to%Y-%m-%dT%H:%M:%SZ
(ISO 8601). -
-v
,--verbose
: Makes the script more verbose.
Mail-Generation Parameters
-
-a
/--attach
: Add the specified files as attachment to the generated mails. Can be specified multiple times. Defaults to none. -
-B
/--bcc
: Add the specified recipients to the BCC list. Can be specified multiple times. Defaults to none. -
-C
/--cc
: Add the specified recipients to the CC list. Can be specified multiple times. Defaults to none. -
-f
/--from
: Specifies the sender mail address to be used. If not explicitly set, implies dry-run mode. Defaults toNobody <nobody@example.com>
. -
-R
/--reply-to
: Specifies the reply-to mail address to be used. Defaults to none. -
--sign
: Specifies the cryptographic signature method to be used. Can be empty (""
) orgpg
. Defaults to none. -
--sign-arg
: Specifies additional arguments to be passed to the function call that signs the mail. Defaults to none. -
--sign-init-arg
: Specifies additional arguments to be passed to the function call that initializes the mail-signing mechanism. Defaults to none. -
-s
/--subject
: Specifies the mail subject to be used. Defaults toSecurity Challenge Message -- {campaign}{infix}
. -
-T
/--to
: Specifies the recipient mail address to be used. Defaults to{firstname} {lastname} <{email}>
.
SMTP-Related Parameters
-
-F
/--force
: Forces to use insecure login if no TLS/SSL is enabled. Defaults to false. -
-S
/--smtpserver
: Specifies the SMTP server to be used for sending the mails. If a port is explicitly specified with the<host>:<port>
syntax, it takes precedence over any implied and explicit port specification using thesmtpport
switch. Defaults tolocalhost
. -
--smtpport
: Specifies the SMTP port to be used. Takes precedence over implied ports (but not over the explicit port specification in the server specification, if present). Defaults to 25. -
--smtpuser
: Specifies the SMTP user to be used for sending mails. Implies TLS and port 465 unless STARTTLS is specified. Defaults to none. -
--smtppass
: Specifies the SMTP password to be used for sending mails. Implies TLS and port 465 unless STARTTLS is specified. Will be queried interactively if set to-
. Defaults to none. -
--starttls
: Use STARTTLS to send mails. Implies port 587. Defaults to none.
Webserver-Related Parameters
-
-H
/--hashstring
: Specifies the string to be hashed for the URL. Defaults to{salt}{campaign}{infix}-{site}
. -
--salt
: Specifies the salt value to be used for hashing. Defaults to a random 8-byte hex string. -
-u
/--url
: Specifies the URL template to use for the target webserver. Defaults to{webserver}/{campaign}{infix}-{hash}
. -
-U
/--createurl
: Specifies the URL to be used for "activating" each site's challenge. Defaults to{webserver}/{campaign}{infix}-{hash}/create
. -
-w
/--webserver
Specifies the web server to use as target. If not set, implies dry-run mode. To suppress web-hook calling in general (for instance, just to send out a batch of mails without any intended web interaction), set to empty string (""
). Defaults to `https://challenge.example.com.
Example Calls
Note: In all examples, the option --dry-run
will be used if necessary, so
that copy-and-pasting the examples does not lead to e-mails being sent by
mistake.
The simplest invocation of the script is this:
./createMails.py
Assuming that the sample directory is present and containing the sample mail template and input list, this call takes all the default values, creates a mail for each entry in the default input list, and saves that. Since no sender e-mail and webserver address is given, dry-mode is implied, so no mails are actually sent, nor is any web call actually made.
The output should look something like this:
DRY RUN. Not actually sending e-mails or creating targets, just creating mail files and URLs.
Writing mail to Mails/Test/DFN-CERT/2024-08-16T10:23:43Z.eml
The minimal set of parameters that must be given is the sender e-mail and
the target webserver to be used. To send a mail without any webserver
reference, set the webserver to the empty string; an minimal example
invocation that would actually send e-mails (if --dry-run
was not set) is
this:
./createMails.py --dry-run --from "Tobias Dussa <dussa@dfn-cert.de>" --webserver ""
Notice that since no target webserver is specified, the URL
variable in
the default mail template does not make much sense, but you can still use
it -- it will just not contain any complete URL.
To be able to identify individual test runs, you can add an infix to the
invocation. This will (by default) insert the infix into several file
names, in particular, into the input file name; therefore, in order to run
the following command, you need to copy the sample input file to a new file
as well. Note that while the infix is just a positional argument, since it
begins with a dash in this example, we need to make sure that it is
interpreted as a positional argument, not as a usage of the -R
(reply-to)
parameter by adding two dashes first.
cp Mails/Test/Input.lst Mails/Test/Input-Run_A.lst
./createMails.py --dry-run --from "Tobias Dussa <dussa@dfn-cert.de>" --webserver "" -- -Run_A
DRY RUN. Not actually sending e-mails or creating targets, just creating mail files and URLs.
Writing mail to Mails/Test/DFN-CERT/2024-08-16T10:34:11Z-Run_A.eml
Generally, you will likely want to specify the campaign name. This then requires a proper directory with the right input files, so it will not work with the sample files, but you can set the campaign name like this:
./createMails.py --campaign MyCampaign
The relevant files are then expected to be in Mails/MyCampaign/
, and
mail files are written in that directory as well.
The following example modifies the mail subject:
./createMails.py --subject "This is just a simple mail subject"
Likewise, you can specify a reply-to address to be used with the
-R
/--reply-to
parameter.
To add additional mail recipients to the CC header, you can do this:
./createMails.py --cc mail@example.com
You can use the same mechanism for BCC recipients and for file attachments. All these parameters can be used multiple times to specify multiple additional recipients or attachments:
./createMails.py --bcc foo@example.com --bcc bar@example.com --cc baz@example.com --attach createMails.py
Cryptographic signatures can be added as well. At the moment, the only supported backend is GPG. The following call will invoke GPG and sign the mail with the default key.
./createMails.py --sign gpg
You can also specify a different key to be used by passing call options to the signing command:
./createMails.py --sign gpg --sign-arg "keyid=0x1234567890ABCDEF"
You can also specify a different directory to be used as GnuPG home by passing call options to the signing command:
./createMails.py --sign gpg --sign-init-arg "gnupghome=/some/dir"
By default, mails are sent to localhost on port 25 using plain SMTP. To use a different mail server, you need to specify the server to be used:
./createMails.py --smtpserver smtp.example.com
If you need to log in to send a mail, you can do so as well. This will imply TLS and set the port to 465. To override this, you need to set the port yourself.
./createMails.py --smtpuser user --smtppass pass
If you do not want to specify the SMTP password on the command line for security reasons, you can set the password to a dash, and you will be prompted for the password interactively:
./createMails.py --smtpuser user --smtppass -
An actual invocation will obviously combine a lot of the above parameters:
./createMails.py --dry-run \
--smtpserver smtp.example.com --smtpuser user --smtppass pass \
--from "Sender Dude <sender@example.com>" \
--cc "CC Recipient <cc@example.com>" \
--bcc bcc@example.com \
--reply-to reply@example.com \
--sign gpg
--campaign SampleCommsChallenge2024 \
--webserver https://landing.example.com