DMARC: first stab at implementing the interface.

This commit is contained in:
Philippe PITTOLI 2024-04-12 12:52:43 +02:00
parent c4735e9efc
commit aca29458a0
5 changed files with 47 additions and 5 deletions

View File

@ -57,6 +57,7 @@ import App.Type.ResourceRecord (ResourceRecord, emptyRR
, mechanism_types, qualifier_types, modifier_types) , mechanism_types, qualifier_types, modifier_types)
import App.Type.ResourceRecord (Mechanism, Modifier, Qualifier(..)) as RR import App.Type.ResourceRecord (Mechanism, Modifier, Qualifier(..)) as RR
import App.Type.DKIM as DKIM import App.Type.DKIM as DKIM
import App.Type.DMARC as DMARC
import App.DisplayErrors (error_to_paragraph) import App.DisplayErrors (error_to_paragraph)
@ -181,6 +182,8 @@ data Action
-- | Add a SPF modifier to the currently modified (SPF) entry (see `_currentRR`). -- | Add a SPF modifier to the currently modified (SPF) entry (see `_currentRR`).
| SPF_Modifier_Add | SPF_Modifier_Add
| DMARC_policy Int
| DKIM_hash_algo Int | DKIM_hash_algo Int
| DKIM_sign_algo Int | DKIM_sign_algo Int
| DKIM_pubkey String | DKIM_pubkey String
@ -203,6 +206,7 @@ string_to_acceptedtype str = case str of
"SRV" -> Just SRV "SRV" -> Just SRV
"SPF" -> Just SPF "SPF" -> Just SPF
"DKIM" -> Just DKIM "DKIM" -> Just DKIM
"DMARC" -> Just DMARC
_ -> Nothing _ -> Nothing
data Tab = Zone | TheBasics | TokenExplanation data Tab = Zone | TheBasics | TokenExplanation
@ -233,6 +237,7 @@ type State =
, spf_modifier_v :: String , spf_modifier_v :: String
, dkim :: DKIM.DKIM , dkim :: DKIM.DKIM
, dmarc :: DMARC.DMARC
, _zonefile :: Maybe String , _zonefile :: Maybe String
@ -285,6 +290,7 @@ initialState domain =
, spf_modifier_t: "redirect" , spf_modifier_t: "redirect"
, spf_modifier_v: "" , spf_modifier_v: ""
, dkim: DKIM.emptyDKIMRR , dkim: DKIM.emptyDKIMRR
, dmarc: DMARC.emptyDMARCRR
, current_tab: Zone , current_tab: Zone
} }
@ -353,6 +359,7 @@ render state
"SRV" -> template modal_content_srv (foot_content SRV) "SRV" -> template modal_content_srv (foot_content SRV)
"SPF" -> template modal_content_spf (foot_content SPF) "SPF" -> template modal_content_spf (foot_content SPF)
"DKIM" -> template modal_content_dkim (foot_content DKIM) "DKIM" -> template modal_content_dkim (foot_content DKIM)
"DMARC" -> template modal_content_dmarc (foot_content DMARC)
_ -> Bulma.p $ "Invalid type: " <> state._currentRR.rrtype _ -> Bulma.p $ "Invalid type: " <> state._currentRR.rrtype
where where
-- DRY -- DRY
@ -494,6 +501,21 @@ render state
, Bulma.box_input "noteDKIM" "Note" "Note for fellow administrators." DKIM_note (fromMaybe "" state.dkim.n) , Bulma.box_input "noteDKIM" "Note" "Note for fellow administrators." DKIM_note (fromMaybe "" state.dkim.n)
] ]
modal_content_dmarc :: Array (HH.HTML w Action)
modal_content_dmarc =
[ Bulma.div_content [Bulma.explanation Explanations.dmarc_introduction]
, render_errors
, Bulma.input_with_side_text "domainDMARC" "Name" "_dmarc"
(updateForm Field_Domain)
state._currentRR.name
display_domain_side
, Bulma.box_input "ttlDMARC" "TTL" "600"
(updateForm Field_TTL)
(show state._currentRR.ttl)
, Bulma.hr
, Bulma.selection_field "idDMARCPolicy" "Policy" DMARC_policy (map show DMARC.policies) (show state.dmarc.p)
]
display_domain_side = (if state._currentRR.name == (state._domain <> ".") then "" else "." <> state._domain) display_domain_side = (if state._currentRR.name == (state._domain <> ".") then "" else "." <> state._domain)
newtokenbtn = Bulma.btn (maybe "🏁​ Ask for a token" (\_ -> "🏁​ Ask for a new token") state._currentRR.token) (NewToken state._currentRR.rrid) newtokenbtn = Bulma.btn (maybe "🏁​ Ask for a token" (\_ -> "🏁​ Ask for a new token") state._currentRR.token) (NewToken state._currentRR.rrid)
foot_content x = foot_content x =
@ -562,6 +584,7 @@ handleAction = case _ of
, q = Just RR.HardFail , q = Just RR.HardFail
} }
default_rr_DKIM = emptyRR { rrtype = "DKIM", name = "default._domainkey", target = "" } default_rr_DKIM = emptyRR { rrtype = "DKIM", name = "default._domainkey", target = "" }
default_rr_DMARC = emptyRR { rrtype = "DMARC", name = "_dmarc", target = "" }
case t of case t of
A -> H.modify_ _ { _currentRR = default_rr_A } A -> H.modify_ _ { _currentRR = default_rr_A }
@ -573,6 +596,7 @@ handleAction = case _ of
SRV -> H.modify_ _ { _currentRR = default_rr_SRV } SRV -> H.modify_ _ { _currentRR = default_rr_SRV }
SPF -> H.modify_ _ { _currentRR = default_rr_SPF } SPF -> H.modify_ _ { _currentRR = default_rr_SPF }
DKIM -> H.modify_ _ { _currentRR = default_rr_DKIM } DKIM -> H.modify_ _ { _currentRR = default_rr_DKIM }
DMARC -> H.modify_ _ { _currentRR = default_rr_DMARC }
-- | Initialize the ZoneInterface component: ask for the domain zone to `dnsmanagerd`. -- | Initialize the ZoneInterface component: ask for the domain zone to `dnsmanagerd`.
Initialize -> do Initialize -> do
@ -741,6 +765,8 @@ handleAction = case _ of
H.modify_ _ { _currentRR { modifiers = new_value }} H.modify_ _ { _currentRR { modifiers = new_value }}
handleAction $ ResetSPF handleAction $ ResetSPF
DMARC_policy v -> H.modify_ _ { dmarc { p = fromMaybe DMARC.None $ DMARC.policies A.!! v } }
DKIM_hash_algo v -> H.modify_ _ { dkim { h = DKIM.hash_algos A.!! v } } DKIM_hash_algo v -> H.modify_ _ { dkim { h = DKIM.hash_algos A.!! v } }
DKIM_sign_algo v -> H.modify_ _ { dkim { k = DKIM.sign_algos A.!! v } } DKIM_sign_algo v -> H.modify_ _ { dkim { k = DKIM.sign_algos A.!! v } }
DKIM_pubkey v -> H.modify_ _ { dkim { p = v } } DKIM_pubkey v -> H.modify_ _ { dkim { p = v } }
@ -998,9 +1024,9 @@ render_new_records _
, Bulma.h1 "Special records about the mail system" , Bulma.h1 "Special records about the mail system"
-- use "level" to get horizontal buttons next to each other (probably vertical on mobile) -- use "level" to get horizontal buttons next to each other (probably vertical on mobile)
, Bulma.level [ , Bulma.level [
Bulma.btn "SPF" (CreateNewRRModal SPF) Bulma.btn "SPF" (CreateNewRRModal SPF)
, Bulma.btn "DKIM" (CreateNewRRModal DKIM) , Bulma.btn "DKIM" (CreateNewRRModal DKIM)
, Bulma.btn_ro (C.is_small <> C.is_warning) "DMARC (soon)" , Bulma.btn "DMARC" (CreateNewRRModal DMARC)
] [] ] []
, Bulma.hr , Bulma.hr
, Bulma.level [ , Bulma.level [

View File

@ -155,6 +155,18 @@ dkim_introduction =
] ]
] ]
dmarc_introduction :: forall w i. Array (HH.HTML w i)
dmarc_introduction =
[ Bulma.p """
DMARC is a spam mitigation mechanism on top of SPF and DKIM.
Upon receiving a mail, the server checks whether the "From:" field of the mail is consistent with the SPF and DKIM
records of the sender's domain.
The DMARC record tells what to do with the mail in case of an inconsistency, and DMARC allows to define email
addresses that should receive error reports.
"""
]
dkim_default_algorithms :: forall w i. Array (HH.HTML w i) dkim_default_algorithms :: forall w i. Array (HH.HTML w i)
dkim_default_algorithms = dkim_default_algorithms =
[ Bulma.p """ [ Bulma.p """

View File

@ -17,6 +17,7 @@ data AcceptedRRTypes
| SRV | SRV
| SPF | SPF
| DKIM | DKIM
| DMARC
derive instance genericAcceptedRRTypes :: Generic AcceptedRRTypes _ derive instance genericAcceptedRRTypes :: Generic AcceptedRRTypes _

View File

@ -85,5 +85,5 @@ codecVersion = CA.prismaticCodec "Version" str_to_version generic_serialization
str_to_version :: String -> Maybe Version str_to_version :: String -> Maybe Version
str_to_version = case _ of str_to_version = case _ of
"dkim1" -> Just DKIM1 "dkim1" -> Just DKIM1
_ -> Nothing _ -> Nothing

View File

@ -203,6 +203,9 @@ data Policy
-- | "Reject" means to not accept any failure of DKIM or SPF. -- | "Reject" means to not accept any failure of DKIM or SPF.
| Reject | Reject
policies :: Array Policy
policies = [None, Quarantine, Reject]
-- | Codec for just encoding a single value of type `Policy`. -- | Codec for just encoding a single value of type `Policy`.
codecPolicy :: CA.JsonCodec Policy codecPolicy :: CA.JsonCodec Policy
codecPolicy = CA.prismaticCodec "Policy" str_to_policy generic_serialization CA.string codecPolicy = CA.prismaticCodec "Policy" str_to_policy generic_serialization CA.string