Rotate your DKIM Keys
As email admins, we often overlook one of the most important routine tasks in email administration... looking after our DKIM keys. They need rotating periodically, let's automate that.
Let's face it, day to day we have so many little routine tasks that we need to complete, it's easy to overlook some of the ones that seem less important... DKIM keys are certainly one of those tasks. We set up DKIM, email is flowing, everything is authenticated, there's no issues, so we forget all about it.
Let's step back for just a moment... what exactly is DKIM?
DKIM (or DomainKeys Identified Mail) is an email authentication method that uses a digital signature to verify that an email is authentic and hasn't been changed in transit. It's a way of verifying that an email sent by a mail server, hasn't been intercepted, modified, or altered since it was sent.
How does it work?
DKIM works with public/private key encryption. The private key is generated on the email server and stored there; the public key is then uploaded to the domain's public DNS zone, so other email servers can decrypt the DKIM signature and verify the email's authenticity.
Firstly, the email server determines what exactly they want to include in their DKIM signature; usually this includes the "from" address, the body, and the subject. It can contain more, but we'll stick to the basics for this example. These fields determined by the email server must remain unchanged during transit, if for any reason those fields are tampered with DKIM authentication will fail.
Secondly, the sender's email server generates a hash of those text fields. For example, the following text fields,
From: Chris Greenacre <chris.greenacre@tophhie.co.uk>
Subject: DKIM
would map to this hash string
48b3121ff3fcf18c7760c668f5019e272f07cc7fb76fba88b74a72d766d77309
The email server then uses its private key and encrypts that hash (usually with rsa-sha or rsa-sha256) and builds the DKIM-Signature header within the email.
The email is then sent!
The receiving email server then looks at that DKIM-Signature, decrypts it using the public key found in the sending domain's public DNS and verifies the message hasn't been modified. If it hasn't, it's DKIM authenticated!
Fast forward, why should I rotate my DKIM keys?
DKIM key rotation is the process of generating a new pair of public and private keys to sign and authenticate outgoing emails and then stop using the old keys.
Essentially, this boils down to theft. If your email environment becomes compromised, or a malicious source manages to gain access to your email server's private keys, they can send DKIM authenticated emails as your domain...
Regular rotation ensures that these hackers won't be able to send phishing or spam emails, as your domain, to manipulate recipients for very long.
Okay, so how often should I be rotating my keys?
The answer to this really comes down to how much time, effort and benefit you see in the process.
Ideally, it's suggested to rotate your keys at least twice per year.
How do I rotate them then?
The process varies massively between email providers, so it's best to research your own email provider's guidance on DKIM keys and their rotation.
However, if you are a pure Exchange Online environment (like we are), we have something that might just help you out, save you some time, and offload the burden of rotating your keys onto an automation service...
Use the below script to rotate the DKIM keys for all your Accepted Domains within Exchange Online.
# Set your tenant name
$tenantName = "{ENTER YOUR TENANT DOMAIN NAME}"
# Set sender email address
$SenderEmailAddress = "{REPLACE WITH SENDER EMAIL ADDRESS}"
# Connect to ExchangeOnline
Connect-ExchangeOnline -ManagedIdentity -Organization $tenantName
# Connect to Microsoft Graph
Connect-MgGraph -Identity
if ($null -eq (Get-MgContext)) {
Write-Error "Failed to connect to Microsoft Graph... exiting..."
exit
}
# Fetch the DKIM signed domains
$AcceptedDomains = (Get-AcceptedDomain).DomainName
$DkimDomains = Get-DkimSigningConfig | ? Enabled -like $True
$SuccessfulDomains = @()
$FailedDomains = @()
$RemovedDomains = @()
# Rotate the DKIM keys
foreach ($Domain in $DkimDomains) {
if ($Domain.Domain -notin $AcceptedDomains) {
Write-Warning "$($Domain) is not one of our accepted domains anymore... disabling..."
Set-DkimSigningConfig -Identity $Domain -Enabled $false -Confirm:$false
$RemovedDomains += $Domain.Domain
continue
}
Write-Output "Rotating Dkim Signing Keys for $($Domain.Domain)..."
try {
Rotate-DkimSigningConfig -Identity $Domain.Domain
Write-Output "Successfully rotated Dkim Signing Keys for $($Domain.Domain)!"
$SuccessfulDomains += $Domain.Domain
} catch {
Write-Output "FAILED to rotate Dkim Signing Keys for $($Domain.Domain)!"
$FailedDomains += $Domain.Domain
}
}
$params = @{
Message = @{
Subject = "Dkim Signing Keys Rotated!"
Body = @{
ContentType = "Html"
Content = "<div>Hi there,</div>
<div> </div>
<div>This is just a quick email to let you know that the Dkim Signing Keys for all domains in Exchange Online have been rotated.</div>
<div> </div>
<div><strong>Domains Successfully Rotated:</strong></div>
<div>$($SuccessfulDomains -join ', ')</div>
<div> </div>
<div><strong>Domains Failed to Rotate:</strong></div>
<div>$($FailedDomains -join ', ')</div>
<div> </div>
<div><strong>Dkim Domains Removed:</strong></div>
<div>$($RemovedDomains -join ', ')</div>
<div> </div>
<div>Dkim domains are removed when they have initially been configured, but have since been removed as an Accepted Domain within the Exchange Online environment.</div>
<div> </div>
<div>Please check Exchange Online PowerShell to verify rotate dates and successful rotation.</div>
<div> </div>
<div>Kind regards,</div>
<div>IT Automation</div>"
}
ToRecipients = @(
@{
EmailAddress = @{
Address = "{REPLACE WITH RECIPIENT EMAIL ADDRESS}"
}
}
)
}
SaveToSentItems = "true"
}
Send-MgUserMail -UserId $SenderEmailAddress -BodyParameter $params
Let's go through what's happening in this script.
- We're connecting to the Exchange Online environment, and Microsoft Graph.
- We're then fetching all the Accepted Domains, and all configured DKIM signing domains.
- We're then looping through all the DKIM signing domains, performing a check to ensure the DKIM domain is still a valid Accepted Domain within Exchange, if it isn't then the DKIM config is removed for the domain, and we add it to the removed domains array. If it is still a valid Accepted Domain, we're rotating the keys.
- If the rotate is successful, we add that domain to the successful array, if it fails, we're adding it to the failed array.
- Once we've finished looping, we issue an email to the appropriate administrator or recipient informing them the rotation has been completed, and outline which domains were successful, which failed, and which were removed.
If you decide to implement this script within Azure Automation, set it on a schedule... that way you never have to perform this task manually again, set the schedule and let Azure Automation rotate your keys for you as frequently or as infrequently as you like!
We have this configured within our Azure Automation instance, running once every six months... it works a treat!
You can feel free to download the script here.
Until next time ππ»