@ -3,7 +3,19 @@
let
cfg = config . services . parsedmarc ;
opt = options . services . parsedmarc ;
ini = pkgs . formats . ini { } ;
isSecret = v : isAttrs v && v ? _secret && isString v . _secret ;
ini = pkgs . formats . ini {
mkKeyValue = lib . flip lib . generators . mkKeyValueDefault " = " rec {
mkValueString = v :
if isInt v then toString v
else if isString v then v
else if true == v then " T r u e "
else if false == v then " F a l s e "
else if isSecret v then hashString " s h a 2 5 6 " v . _secret
else throw " u n s u p p o r t e d t y p e ${ typeOf v } : ${ ( lib . generators . toPretty { } ) v } " ;
} ;
} ;
inherit ( builtins ) elem isAttrs isString isInt isList typeOf hashString ;
in
{
options . services . parsedmarc = {
@ -107,11 +119,35 @@ in
} ;
settings = lib . mkOption {
example = lib . literalExpression ''
{
imap = {
host = " i m a p . e x a m p l e . c o m " ;
user = " a l i c e @ e x a m p l e . c o m " ;
password = { _secret = " / r u n / k e y s / i m a p _ p a s s w o r d " } ;
watch = true ;
} ;
splunk_hec = {
url = " h t t p s : / / s p l u n k h e c . e x a m p l e . c o m " ;
token = { _secret = " / r u n / k e y s / s p l u n k _ t o k e n " } ;
index = " e m a i l " ;
} ;
}
'' ;
description = ''
Configuration parameters to set in
<filename> parsedmarc . ini < /filename > . For a full list of
available parameters , see
< link xlink:href= " h t t p s : / / d o m a i n a w a r e . g i t h u b . i o / p a r s e d m a r c / # c o n f i g u r a t i o n - f i l e " / > .
Settings containing secret data should be set to an attribute
set containing the attribute <literal> _secret < /literal > - a
string pointing to a file containing the value the option
should be set to . See the example to get a better picture of
this : in the resulting <filename> parsedmarc . ini < /filename >
file , the <literal> splunk_hec . token < /literal > key will be set
to the contents of the
<filename> /run/keys/splunk_token < /filename > file .
'' ;
type = lib . types . submodule {
@ -170,11 +206,18 @@ in
} ;
password = lib . mkOption {
type = with lib . types ; nullOr path ;
type = with lib . types ; nullOr ( either path ( attrsOf path ) ) ;
default = null ;
description = ''
The path to a file containing the IMAP server password .
The IMAP server password .
Always handled as a secret whether the value is
wrapped in a <literal> { _secret = . . . ; } < /literal >
attrset or not ( refer to < xref
linkend = " o p t - s e r v i c e s . p a r s e d m a r c . s e t t i n g s " / > for
details ) .
'' ;
apply = x : if isAttrs x || x == null then x else { _secret = x ; } ;
} ;
watch = lib . mkOption {
@ -228,11 +271,18 @@ in
} ;
password = lib . mkOption {
type = with lib . types ; nullOr path ;
type = with lib . types ; nullOr ( either path ( attrsOf path ) ) ;
default = null ;
description = ''
The path to a file containing the SMTP server password .
The SMTP server password .
Always handled as a secret whether the value is
wrapped in a <literal> { _secret = . . . ; } < /literal >
attrset or not ( refer to < xref
linkend = " o p t - s e r v i c e s . p a r s e d m a r c . s e t t i n g s " / > for
details ) .
'' ;
apply = x : if isAttrs x || x == null then x else { _secret = x ; } ;
} ;
from = lib . mkOption {
@ -274,12 +324,19 @@ in
} ;
password = lib . mkOption {
type = with lib . types ; nullOr path ;
type = with lib . types ; nullOr ( either path ( attrsOf path ) ) ;
default = null ;
description = ''
The path to a file containing the password to use when
connecting to Elasticsearch , if required .
The password to use when connecting to Elasticsearch ,
if required .
Always handled as a secret whether the value is
wrapped in a <literal> { _secret = . . . ; } < /literal >
attrset or not ( refer to < xref
linkend = " o p t - s e r v i c e s . p a r s e d m a r c . s e t t i n g s " / > for
details ) .
'' ;
apply = x : if isAttrs x || x == null then x else { _secret = x ; } ;
} ;
ssl = lib . mkOption {
@ -403,12 +460,17 @@ in
# lists, empty attrsets and null. This makes it possible to
# list interesting options in `settings` without them always
# ending up in the resulting config.
filteredConfig = lib . converge ( lib . filterAttrsRecursive ( _ : v : ! builtins . elem v [ null [ ] { } ] ) ) cfg . settings ;
filteredConfig = lib . converge ( lib . filterAttrsRecursive ( _ : v : ! elem v [ null [ ] { } ] ) ) cfg . settings ;
# Extract secrets (attributes set to an attrset with a
# "_secret" key) from the settings and generate the commands
# to run to perform the secret replacements.
secretPaths = lib . catAttrs " _ s e c r e t " ( lib . collect isSecret filteredConfig ) ;
parsedmarcConfig = ini . generate " p a r s e d m a r c . i n i " filteredConfig ;
mkSecretReplacement = file :
lib . optionalString ( file != null ) ''
replace-secret ' $ { file } ' ' $ { file } ' /run/parsedmarc/parsedmarc.ini
'' ;
mkSecretReplacement = file : ''
replace-secret $ { lib . escapeShellArgs [ ( hashString " s h a 2 5 6 " file ) file " / r u n / p a r s e d m a r c / p a r s e d m a r c . i n i " ] }
'' ;
secretReplacements = lib . concatMapStrings mkSecretReplacement secretPaths ;
in
{
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
@ -423,9 +485,7 @@ in
umask u = rwx , g = , o =
cp $ { parsedmarcConfig } /run/parsedmarc/parsedmarc.ini
chown parsedmarc:parsedmarc /run/parsedmarc/parsedmarc.ini
$ { mkSecretReplacement cfg . settings . smtp . password }
$ { mkSecretReplacement cfg . settings . imap . password }
$ { mkSecretReplacement cfg . settings . elasticsearch . password }
$ { secretReplacements }
'' + l i b . o p t i o n a l S t r i n g c f g . p r o v i s i o n . l o c a l M a i l . e n a b l e ''
openssl rand - hex 64 > /run/parsedmarc/dmarc_user_passwd
replace-secret ' @ imap-password @ ' ' /run/parsedmarc/dmarc_user_passwd ' /run/parsedmarc/parsedmarc.ini