An Azure service that is used to automate, configure, and install updates across hybrid environments.
Create one Microsoft Entra Conditional Access Block access policy for the selected accounts, then use an hourly Azure Automation runbook to enable that policy outside 07:30–15:30 Monday–Friday and on dates listed as public holidays.
Conditional Access does not provide a documented time-of-day or holiday condition; its policies evaluate identities, resources, locations, devices, risks, and related signals. Automation is therefore required to change the policy state. Conditional Access licensing is required for the tenant and targeted users, and administration requires an appropriate role such as Conditional Access Administrator.^1^
1. Create the block policy
In the Microsoft Entra admin center:
- Go to Entra ID → Conditional Access → Policies → New policy.
- Under Users or workload identities, include a security group containing only the accounts to restrict.
- Exclude:
- Emergency/break-glass accounts.
- Service accounts that must run continuously.
- Under Target resources, select the specific applications to restrict, or All resources if that is genuinely required.
- Under Grant, select Block access.
- Initially set the policy to Report-only and validate its impact. Microsoft recommends excluding emergency accounts and testing Conditional Access policies before enabling them.^2^
- After testing, set it to Off. Record the policy’s object ID; the runbook will switch it between
enabledanddisabled.
Do not target the Automation identity or administrators needed to recover the configuration.
2. Configure Azure Automation authentication
In the Automation account:
- Under Modules → Browse gallery, import:
-
Microsoft.Graph.Authentication -
Microsoft.Graph.Identity.SignIns
-
- Create an app registration and upload a certificate to both the app registration and Automation account.
- Grant these Microsoft Graph application permissions:
-
Policy.Read.All -
Policy.ReadWrite.ConditionalAccess
-
- Grant tenant-wide admin consent. Microsoft Graph documents these permissions for updating Conditional Access policies.^3^
- Under Shared Resources → Variables, create:
-
ClientId -
TenantId -
Thumbprint -
ConditionalAccessPolicyId -
BusinessTimeZone, using a Windows time-zone ID appropriate for the users -
PublicHolidays, containing comma-separated ISO dates, for example:
-
2026-01-01,2026-04-03,2026-04-06,2026-12-25
Certificate authentication, Automation variables, Graph modules, and admin consent are documented in the Azure Automation and Microsoft Graph integration guidance.^4^
3. Create the runbook
Create a PowerShell runbook and publish this code:
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Identity.SignIns
$clientId = Get-AutomationVariable 'ClientId'
$tenantId = Get-AutomationVariable 'TenantId'
$thumbprint = Get-AutomationVariable 'Thumbprint'
$policyId = Get-AutomationVariable 'ConditionalAccessPolicyId'
$zoneId = Get-AutomationVariable 'BusinessTimeZone'
$holidayText = Get-AutomationVariable 'PublicHolidays'
Connect-MgGraph -ClientId $clientId -TenantId $tenantId `
-CertificateThumbprint $thumbprint -NoWelcome
$zone = [TimeZoneInfo]::FindSystemTimeZoneById($zoneId)
$now = [TimeZoneInfo]::ConvertTimeFromUtc([datetime]::UtcNow, $zone)
$holidays = @($holidayText -split ',' | ForEach-Object {
[datetime]::ParseExact($_.Trim(), 'yyyy-MM-dd', $null).Date
})
$isWeekday = $now.DayOfWeek -notin @('Saturday', 'Sunday')
$isHoliday = $holidays -contains $now.Date
$start = $now.Date.AddHours(7).AddMinutes(30)
$end = $now.Date.AddHours(15).AddMinutes(30)
$isWorkingTime = $isWeekday -and !$isHoliday -and $now -ge $start -and $now -lt $end
$requiredState = if ($isWorkingTime) { 'disabled' } else { 'enabled' }
$policy = Get-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policyId
if ($policy.State.ToString().ToLower() -ne $requiredState) {
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policyId `
-BodyParameter @{ state = $requiredState }
Write-Output "Policy changed to $requiredState at $now"
} else {
Write-Output "No change: policy already $requiredState at $now"
}
The runbook reads the current state first, making repeated execution safe and allowing missed transitions to be corrected at the next run.
4. Schedule and monitor it
Create a recurring hourly schedule starting at 07:30 in the business time zone, then link it to the runbook:
Automation account → Shared Resources → Schedules → Add a schedule
Azure Automation supports time zones, daylight-saving adjustments, and recurring schedules; one hour is its shortest schedule interval.^5^
Test these cases before production:
- Weekday at 07:30: policy becomes
disabled. - Weekday at 15:30: policy becomes
enabled. - Weekend: policy remains
enabled. - Listed holiday: policy remains
enabled. - Invalid holiday value: runbook fails visibly rather than opening access.
Configure monitoring for failed Automation jobs. A failed morning execution leaves access blocked; a failed afternoon execution can leave access open until the next successful hourly reconciliation.
Enforcement limitation
This design controls new authentication and token issuance, but it cannot guarantee that every existing application session ends exactly at 15:30. Access-token and application-session behavior determines when existing access ends, and Microsoft Entra cannot directly revoke session cookies issued by an application.^6^
If an exact hard cutoff is mandatory, the targeted application must support application-specific real-time session enforcement; merely enabling the Conditional Access policy or revoking refresh tokens is insufficient.
References