Skip to content

Instantly share code, notes, and snippets.

@DanClowry
Created December 8, 2021 00:54
Show Gist options
  • Save DanClowry/68bccd3680b84aa96316bda2a568f951 to your computer and use it in GitHub Desktop.
Save DanClowry/68bccd3680b84aa96316bda2a568f951 to your computer and use it in GitHub Desktop.
Script to rollout DKIM to all O365 tenants with Azure DNS
# https://www.cyberdrain.com/connect-to-exchange-online-automated-when-mfa-is-enabled-using-the-secureapp-model/
$ApplicationId = 'xxxx-xxxx-xxx-xxxx-xxxx'
$ApplicationSecret = 'TheSecretTheSecrey' | Convertto-SecureString -AsPlainText -Force
$TenantID = 'YourTenantID'
$RefreshToken = 'RefreshToken'
$ExchangeRefreshToken = 'ExchangeRefreshToken'
$upn = 'UPN-Used-To-Generate-Tokens'
$credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret)
$azureResourceGroup = "YourAzureResourceGroupName"
$aadGraphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant $tenantID
$graphToken = New-PartnerAccessToken -ApplicationId $ApplicationId -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant $tenantID
Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken
$customers = Get-MsolPartnerContract -All
Connect-AzAccount
# Get a list of all domains in Azure DNS so we can skip setting up DKIM for domains we don't manage
$azureDomains = @{}
Get-AzDnsZone -ResourceGroupName $azureResourceGroup | ForEach-Object { $azureDomains[$_.Name] = $_.Name }
Write-Output "Got $($azureDomains.Count) domains from Azure DNS"
foreach ($customer in $customers) {
$token = New-PartnerAccessToken -ApplicationId 'a0c73c16-a7e3-4564-9a95-2bdf47383716'-RefreshToken $ExchangeRefreshToken -Scopes 'https://outlook.office365.com/.default' -Tenant $customer.TenantId
$tokenValue = ConvertTo-SecureString "Bearer $($token.AccessToken)" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($upn, $tokenValue)
$customerId = $customer.DefaultDomainName
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell-liveid?DelegatedOrg=$($customerId)&BasicAuthToOAuthConversion=true" -Credential $credential -Authentication Basic -AllowRedirection
Import-PSSession $session
Write-Output "Connected to $($customerId) $($customer.TenantId)"
$domains = Get-AcceptedDomain
foreach ($domain in $domains) {
# Skip domains in the tenant that aren't in Azure DNS
if (!$azureDomains.ContainsKey($domain.Name)) {
Write-Output "Skipping $($domain.Name) - domain not in Azure DNS"
continue
}
$dkimConfig = Get-DkimSigningConfig -Identity $domain.Name
# Skip domains where DKIM is already enabled
if ($dkimConfig.Enabled) {
Write-Output "Skipping $($domain.Name) - DKIM already enabled"
continue
}
# Create DKIM keys if Get-DkimSigningConfig fails
if ($? -eq $false) {
New-DkimSigningConfig -DomainName $domain.Name -Enabled $false
Write-Output "DKIM keys created for $($domain.Name)"
}
else {
Write-Output "DKIM keys already created for $($domain.Name)"
}
$dkimConfig = Get-DkimSigningConfig -Identity $domain.Name
New-AzDnsRecordSet -Name selector1._domainkey -RecordType CNAME -ZoneName $domain.Name -ResourceGroupName $azureResourceGroup -Ttl 3600 -DnsRecords (New-AzDnsRecordConfig -Cname $dkimConfig.Selector1CNAME)
New-AzDnsRecordSet -Name selector2._domainkey -RecordType CNAME -ZoneName $domain.Name -ResourceGroupName $azureResourceGroup -Ttl 3600 -DnsRecords (New-AzDnsRecordConfig -Cname $dkimConfig.Selector2CNAME)
Write-Output "Domainkey selectors added to $($domain.Name) zone"
Start-Sleep 10
Write-Host "Sleeping for 10 seconds before checking DKIM"
for ($i = 0; $i -lt 10; $i++) {
Set-DkimSigningConfig -Identity $domain.Name -Enabled $true -ErrorVariable ErrorEnableDKIM
# This doesnt actually work...
if ($ErrorEnableDKIM) {
Write-Output "Error when enabling DKIM. Likely need to wait for DNS to take effect. Waiting 10 seconds... (attempt $($i+1)/10)"
Start-Sleep 10
}
else {
Write-Host "DKIM enabled for $($domain.Name)"
break
}
}
}
Remove-PSSession $session
Write-Output "Disconnected from $($customerId) $($customer.TenantId)"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment