Skip to content

Commit

Permalink
Merge pull request #73 from johnduprey/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
KelvinTegelaar authored Nov 21, 2021
2 parents 581bd93 + 87c9189 commit ee65ae5
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 23 deletions.
17 changes: 15 additions & 2 deletions DNSHelper.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,28 @@ function Read-MXRecord {

# Attempt to identify mail provider based on MX record
if (Test-Path 'MailProviders') {
$ReservedVariables = @{
'DomainNameDashNotation' = $Domain -replace '\.', '-'
}

Get-ChildItem 'MailProviders' -Exclude '_template.json' | ForEach-Object {
try {
$Provider = Get-Content $_ | ConvertFrom-Json -ErrorAction Stop
$MXRecords.Hostname | ForEach-Object {
if ($_ -match $Provider.MxMatch) {
$MXResults.MailProvider = $Provider
if (($Provider.SpfReplace | Measure-Object | Select-Object -ExpandProperty Count) -gt 0) {
$Replace = foreach ($Var in $Provider.SpfReplace) { $Var }
$ExpectedInclude = $Provider.SpfInclude -f $Matches.$Replace
$ReplaceList = New-Object System.Collections.ArrayList
foreach ($Var in $Provider.SpfReplace) {
if ($ReservedVariables.Keys -contains $Var) {
$ReplaceList.Add($ReservedVariables.$Var) | Out-Null
}
else {
$ReplaceList.Add($Matches.$Var) | Out-Null
}
}

$ExpectedInclude = $Provider.SpfInclude -f ($ReplaceList -join ',')
}
else {
$ExpectedInclude = $Provider.SpfInclude
Expand Down
53 changes: 32 additions & 21 deletions ListMFAUsers/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,64 @@ using namespace System.Net
param($Request, $TriggerMetadata)

$APIName = $TriggerMetadata.FunctionName
Log-Request -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug"
Log-Request -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'


# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
Write-Host 'PowerShell HTTP trigger function processed a request.'
#Let's hack the provisioning API to get per user MFA
$AADGraphtoken = (Get-GraphToken -scope "https://graph.windows.net/.default")
$tenantid = ((Get-Content "tenants.cache.json" | ConvertFrom-Json) | Where-Object -Property DefaultDomainName -EQ $Request.Query.TenantFilter).CustomerID
$AADGraphtoken = (Get-GraphToken -scope 'https://graph.windows.net/.default')
$tenantid = ((Get-Content 'tenants.cache.json' | ConvertFrom-Json) | Where-Object -Property DefaultDomainName -EQ $Request.Query.TenantFilter).CustomerID
$TrackingGuid = New-Guid
$LogonPost = @"
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://provisioning.microsoftonline.com/IProvisioningWebService/MsolConnect</a:Action><a:MessageID>urn:uuid:$TrackingGuid</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><UserIdentityHeader xmlns="http://provisioning.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><BearerToken xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">$($AADGraphtoken['Authorization'])</BearerToken><LiveToken i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService"/></UserIdentityHeader><ClientVersionHeader xmlns="http://provisioning.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ClientId xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">50afce61-c917-435b-8c6d-60aa5a8b8aa7</ClientId><Version xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">1.2.183.57</Version></ClientVersionHeader><ContractVersionHeader xmlns="http://becwebservice.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><BecVersion xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">Version47</BecVersion></ContractVersionHeader><TrackingHeader xmlns="http://becwebservice.microsoftonline.com/">$($TrackingGuid)</TrackingHeader><a:To s:mustUnderstand="1">https://provisioningapi.microsoftonline.com/provisioningwebservice.svc</a:To></s:Header><s:Body><MsolConnect xmlns="http://provisioning.microsoftonline.com/"><request xmlns:b="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><b:BecVersion>Version4</b:BecVersion><b:TenantId i:nil="true"/><b:VerifiedDomain i:nil="true"/></request></MsolConnect></s:Body></s:Envelope>
"@
$DataBlob = (Invoke-RestMethod -Method POST -Uri "https://provisioningapi.microsoftonline.com/provisioningwebservice.svc" -ContentType "application/soap+xml; charset=utf-8" -Body $LogonPost).envelope.header.BecContext.DataBlob.'#text'
$DataBlob = (Invoke-RestMethod -Method POST -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -ContentType 'application/soap+xml; charset=utf-8' -Body $LogonPost).envelope.header.BecContext.DataBlob.'#text'

$MSOLXML = @"
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://provisioning.microsoftonline.com/IProvisioningWebService/ListUsers</a:Action><a:MessageID>urn:uuid:$TrackingGuid</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><UserIdentityHeader xmlns="http://provisioning.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><BearerToken xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">$($AADGraphtoken['Authorization'])</BearerToken><LiveToken i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService"/></UserIdentityHeader><BecContext xmlns="http://becwebservice.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><DataBlob xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">$DataBlob</DataBlob><PartitionId xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">2</PartitionId></BecContext><ClientVersionHeader xmlns="http://provisioning.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ClientId xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">50afce61-c917-435b-8c6d-60aa5a8b8aa7</ClientId><Version xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">1.2.183.57</Version></ClientVersionHeader><ContractVersionHeader xmlns="http://becwebservice.microsoftonline.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><BecVersion xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService">Version47</BecVersion></ContractVersionHeader><TrackingHeader xmlns="http://becwebservice.microsoftonline.com/">4e6cb653-c968-4a3a-8a11-2c8919218aeb</TrackingHeader><a:To s:mustUnderstand="1">https://provisioningapi.microsoftonline.com/provisioningwebservice.svc</a:To></s:Header><s:Body><ListUsers xmlns="http://provisioning.microsoftonline.com/"><request xmlns:b="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration.WebService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><b:BecVersion>Version16</b:BecVersion><b:TenantId>$($tenantid)</b:TenantId><b:VerifiedDomain i:nil="true"/><b:UserSearchDefinition xmlns:c="http://schemas.datacontract.org/2004/07/Microsoft.Online.Administration"><c:PageSize>500</c:PageSize><c:SearchString i:nil="true"/><c:SortDirection>Ascending</c:SortDirection><c:SortField>None</c:SortField><c:AccountSku i:nil="true"/><c:BlackberryUsersOnly i:nil="true"/><c:City i:nil="true"/><c:Country i:nil="true"/><c:Department i:nil="true"/><c:DomainName i:nil="true"/><c:EnabledFilter i:nil="true"/><c:HasErrorsOnly i:nil="true"/><c:IncludedProperties i:nil="true" xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/><c:IndirectLicenseFilter i:nil="true"/><c:LicenseReconciliationNeededOnly i:nil="true"/><c:ReturnDeletedUsers i:nil="true"/><c:State i:nil="true"/><c:Synchronized i:nil="true"/><c:Title i:nil="true"/><c:UnlicensedUsersOnly i:nil="true"/><c:UsageLocation i:nil="true"/></b:UserSearchDefinition></request></ListUsers></s:Body></s:Envelope>
"@
$Users = (Invoke-RestMethod -Uri "https://provisioningapi.microsoftonline.com/provisioningwebservice.svc" -Method post -Body $MSOLXML -ContentType 'application/soap+xml; charset=utf-8').envelope.body.ListUsersResponse.listusersresult.returnvalue.results.user
$SecureDefaultsState = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy" -tenantid $Request.query.TenantFilter ).IsEnabled
$Users = (Invoke-RestMethod -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -Method post -Body $MSOLXML -ContentType 'application/soap+xml; charset=utf-8').envelope.body.ListUsersResponse.listusersresult.returnvalue.results.user
$SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $Request.query.TenantFilter ).IsEnabled
$CAState = New-Object System.Collections.ArrayList
try {
$CAPolicies = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies" -tenantid $Request.query.TenantFilter )
$CAState = foreach ($Policy in $CAPolicies) {
$ExcludeUsers = New-Object System.Collections.ArrayList
$CAPolicies = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $Request.query.TenantFilter )

foreach ($Policy in $CAPolicies) {
if (($policy.grantControls.builtincontrols -eq 'mfa') -or ($policy.grantControls.customAuthenticationFactors -eq 'RequireDuoMfa')) {
if ($Policy.conditions.applications.includeApplications -ne "All") {
if ($Policy.conditions.applications.includeApplications -ne 'All') {
Write-Host $Policy.conditions.applications.includeApplications
"Specific Applications"
$CAState.Add('Specific Applications') | Out-Null
continue
}
if ($Policy.conditions.users.includeUsers -eq "All") {
'All Users'
if ($Policy.conditions.users.includeUsers -eq 'All') {
$CAState.Add('All Users') | Out-Null
$ExcludeUsers = $Policy.conditions.users.excludeUsers
continue
}
}
}
} catch {
$CAState = $null
}
if (!$CAState) { $CAState = "None" }
catch {}
if (($CAState | Measure-Object | Select-Object -ExpandProperty Count) -eq 0) { $CAState.Add('None') | Out-Null }
Try {
$MFARegistration = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/reports/credentialUserRegistrationDetails" -tenantid $Request.query.TenantFilter)
} catch {
$MFARegistration = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/reports/credentialUserRegistrationDetails' -tenantid $Request.query.TenantFilter)
}
catch {
$MFARegistration = $null
}
# Interact with query parameters or the body of the request.
$GraphRequest = $Users | ForEach-Object {

$PerUser = if ($_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state -ne $null) { $_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state } else { "Disabled" }
$UserCAState = New-Object System.Collections.ArrayList
if ($CAState -contains 'All Users') {
if ($ExcludeUsers -contains $_.ObjectId) { $UserCAState.Add('Excluded from All Users') | Out-Null }
else { $UserCAState.AddRange($CAState) | Out-Null }
}
else {
$UserCAState = $CAState
}
$PerUser = if ($_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state -ne $null) { $_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state } else { 'Disabled' }
$AccountState = if ($_.BlockCredential -eq $true) { $false } else { $true }

$MFARegUser = if (($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).IsMFARegistered -eq $null) { $false } else { ($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).IsMFARegistered }
Expand All @@ -59,7 +70,7 @@ $GraphRequest = $Users | ForEach-Object {
AccountEnabled = $AccountState
PerUser = $PerUser
MFARegistration = $MFARegUser
CoveredByCA = ($CAState -join ", ")
CoveredByCA = ($UserCAState -join ', ')
CoveredBySD = $SecureDefaultsState
}
}
Expand Down
10 changes: 10 additions & 0 deletions MailProviders/AppRiver.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Name": "AppRiver",
"MxMatch": "arsmtp.com",
"SpfInclude": "{0}.spf.smtp25.com",
"SpfReplace": ["DomainNameDashNotation"],
"Selectors": [""],
"_MxComment": "https://cp.appriver.com/Help/SpamLab%20Administrator%20Help/desktop/Administrator_Services/SpamLab/Alerts_MX_Records.htm",
"_SpfComment": "https://cp.appriver.com/ngp/admin/system-setup",
"_DkimComment": "https://cp.appriver.com/ngp/dkim/"
}
9 changes: 9 additions & 0 deletions MailProviders/Intermedia.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Name": "Intermedia",
"MxMatch": "(:?east|west).smtp.mx.exch[0-9]+.serverdata.net",
"SpfInclude": "spf.intermedia.net",
"Selectors": [""],
"_MxComment": "https://kb.intermedia.net/article/903",
"_SpfComment": "https://kb.intermedia.net/article/1010",
"_DkimComment": "https://kb.intermedia.net/article/36857"
}

0 comments on commit ee65ae5

Please sign in to comment.