Procedure Description
This procedure covers the two reports Atmosera sends UnitedLex around every scheduled Azure Update Manager maintenance window.
- The pre-patching report tells the client which machines are due to be patched and what the window is expected to fix.
- The post-patching report confirms what was installed and lists anything that needs attention.
The technician runs both scripts, checks the output, resolves the exceptions the reports raise, and sends the finished emails to the client.
Every maintenance window has a calendar event. The event holds the schedule and links to this article and to the scripts. Work from the calendar event. Everything you need starts there.
Each window needs two runs.
| Run | When to run it |
|---|---|
| Pre-patching report | At least 30 minutes before the window starts |
| Post-patching report | After the window has closed |
The 30 minute lead time is a minimum, not a target. Machines that are powered off or have never been assessed have to be started and assessed before the report is accurate, and that work takes time. If a large number of machines come back unassessed, allow longer.
Requirements
Prerequisites
PowerShell 7.0 or later. Windows PowerShell 5.1 does not work.
Access to Azure Government (portal.azure.us) for the UnitedLex tenant.
Notepad or another plain-text editor. Notepad is preferred because it displays the email in the same layout the client receives.
Applicability
This procedure applies to the recurring pre-patching notification and post-patching completion reporting performed for UnitedLex around each scheduled Azure Update Manager maintenance window.
Scope Inclusion
- Running both scripts against the UnitedLex tenant.
- Checking the terminal output and the rendered email for each run.
- Starting machines that are powered off and running an assessment on machines that returned none.
- Remediating patch failures inside the approved window using the steps in this article.
- Sending both emails and the post-patching CSV to the client.
Scope Exclusion
Any tenant other than UnitedLex tenant c8f209d5-29ac-4e66-ac26-4e7cfad5a90a.
Creating, modifying, or deleting maintenance configurations, patch groups, dynamic scopes, or schedules.
Risk Assessment
- Both scripts only read from Azure. They do not change anything, so the risk of causing an outage by running them is minimal.
- The one risk worth watching is running against the wrong tenant. The tenant ID is printed during authentication. Confirm it on every run.
Documentation
One client-facing ticket per maintenance window. It is the only ticket used.
| Change Request | Internal Ticket | Client-Facing Ticket | |
If other, specify here.
Advanced
The table below outlines the support level at which the SOP is expected to be actioned and escalated, or what items are expected to be completed at what level.
| Technician | |
Administrator | Engineer |
Procedure Details
Before running the pre-patching report, open one client-facing ticket for the window.
Subject: UnitedLex - Scheduled Patching - [Patch Group] - [Window Date]
Add a first internal note containing the patch groups and window start time taken from the calendar event, plus a link to the calendar event itself.
1. Open PowerShell 7
Launch PowerShell 7 from Start > PowerShell 7 (x64). Confirm the version.
$PSVersionTable.PSVersionThe major version must be 7.
2. Change to the script directory
Set-Location "C:\exampleuser\exampledirectory\PowerShell_Scripts"3. Connect to the United Lex Tenant
Connect-AzAccount -TenantId c8f209d5-29ac-4e66-ac26-4e7cfad5a90a -Environment AzureUSGovernmentConfirm the Azure context
Get-AzContextConfirm the tenant shown is c8f209d5-29ac-4e66-ac26-4e7cfad5a90a. If it is not, or if no context exists, authenticate again
Part A - Pre-Patching Report
Run this at least 30 minutes before the window opens, so the client receives advance notice and you have time to resolve anything the report raises.
Technician Steps
A1. Run the pre-patching script
The Pre Patching Script can be found here: Get-AumPrePatchingReport.ps1
./Get-AumPrePatchingReport.ps1 -DaysAhead 1 -Tenantid c8f209d5-29ac-4e66-ac26-4e7cfad5a90a -NonInteractive
-DaysAhead 1 covers the next day and is the value to use for a normal run. Use a larger number only when catching up on a missed report or when the client asks for a longer view, and record the value in the ticket.
The terminal refers to this value as the horizon. It means the number of days ahead the report looks. Nothing more.
A2. Watch the terminal output
The script runs eight steps.
| Step | What to confirm |
|---|---|
| Step 1 of 8 - Configuration | Tenant and horizon are correct |
| Step 2 of 8 - Authenticating to Azure | Tenant ID matches UnitedLex |
| Step 3 of 8 - Resolving subscription scope | 4 enabled subscriptions resolved |
| Step 4 of 8 - Finding maintenance windows | At least one window occurrence found |
| Step 5 of 8 - Resolving patch group membership | Static and dynamic membership rows returned |
| Step 6 of 8 - Fetching Update Manager assessments | Assessment row count returned |
| Step 7 of 8 - Fetching OS vulnerability data | Findings and CVE rows returned |
| Step 8 of 8 - Correlating and rendering email | Email written to the output path |
If Step 4 returns zero window occurrences, no maintenance is scheduled in that period. Check the calendar event before concluding that no notification is needed.
Example output. This example was run with -DaysAhead 30 so the numbers are larger than a normal run.
============================================================
Get-AumPrePatchingReport v2.0.0
Azure Update Manager pre-patching email generator
READ-ONLY: queries Azure, reads public data, writes local files only.
============================================================
[INFO] Module 'Az.Accounts' already present.
[INFO] Module 'Az.ResourceGraph' already present.
Step 1 of 8: Configuration
[INFO] Tenant: c8f209d5-29ac-4e66-ac26-4e7cfad5a90a | Subs: ALL | Horizon: 30d
[OK] Configuration resolved
Step 2 of 8: Authenticating to Azure
[OK] Authenticated (tenant c8f209d5-29ac-4e66-ac26-4e7cfad5a90a)
Step 3 of 8: Resolving subscription scope
[INFO] Subscription scope: 4 enabled subscription(s).
[OK] Subscription scope resolved
Step 4 of 8: Finding maintenance windows (next 30 days)
[OK] 8 window occurrence row(s) found
Step 5 of 8: Resolving patch group membership
[OK] 22 static + 41 dynamic membership row(s)
Step 6 of 8: Fetching Update Manager assessments
[OK] 9 assessment row(s)
Step 7 of 8: Fetching OS vulnerability data (Defender for Cloud)
[OK] 58 finding(s), 8047 CVE row(s)
Step 8 of 8: Correlating and rendering email
[OK] Email written to ...\aum_prepatch_20260909_1401.mdA3. Read the EXECUTION SUMMARY
============================================================
EXECUTION SUMMARY
============================================================
Patch groups found: 8
Target VMs: 35
VMs assessed: 9
OS vuln findings: 58
Time elapsed: 00:15
[OK] All datasets returned. Clean run.Compare Target VMs with VMs assessed. Any gap means machines returned no assessment data and must be handled in A5. In the example above, 35 target VMs against 9 assessed means 26 machines need attention.
Note that the clean run message only means the script reached every data source it needed. It does not mean every machine was assessed. Always compare the two numbers yourself.
A4. Open the output in Notepad
Open the email in Notepad. Substitute the real filename. The full path is printed on the last line of the run.
notepad .\aum_prepatch_YYYYMMDD_HHMM.md
A5. Resolve machines with no assessment data
In the Target Resources table, find rows where Reboot Required reads Assessment pending and the Critical/Security and Other columns both show a dash. Those machines returned no assessment data.
For each affected machine.
- In the Azure portal, go to Virtual machines > select the machine > Overview.
- If the machine is not running, start it. Machines in a patch group are expected to be powered on for patching.
- Wait for the status to reach Running and for the guest agent to report ready.
- Go to Azure Update Manager > Machines > select the machine > Check for updates to trigger an on-demand assessment.
- Wait for the assessment to finish. This usually takes several minutes and takes longer on machines that have not been assessed in a while.
- Repeat for every machine showing as pending.
A6. Re-run the pre-patching script
Run the exact command from A1 again. Target VMs and VMs assessed should now match, and every row in the Target Resources table should show a reboot value and update counts instead of a pending assessment.
If a machine still reports no assessment data after a completed assessment, escalate to an Administrator. Leave the machine in the report.
A7. Check any footnotes on the window table
The report may include a footnote like the one in the example above, stating that no target resources could be resolved for a patch group.
This happens when the group targets machines in a subscription the script did not query. It is expected behaviour. Check the affected group against the calendar event, record what you saw in an internal note, and leave the window in the client email.
If a patch group that should return machines returns none, escalate to an Administrator.
A8. Send the pre-patching email
- Paste the rendered email into the ticket as a public reply and send it to UnitedLex.
- Add an internal note recording the
-DaysAheadvalue used and any machines you powered on or assessed manually. - Attach the
.mdand.logfiles to that internal note.
Part B - Post-Patching Report
Run this after the maintenance window has closed, so the client receives confirmation of what was installed and what still needs attention.
Technician Steps
B1. Run the script
The Post Patching Script can be found here: Get-AumPostPatchReport.ps1
./Get-AumPostPatchReport.ps1 -LookbackDays 1 -TenantId c8f209d5-29ac-4e66-ac26-4e7cfad5a90a
-LookbackDays 1 covers the window that has just closed and is the value to use for a normal run. Widen it only when catching up on a missed report, and record the value in the ticket.
B2. Watch the terminal output
The script runs six steps. Note every WARN line as it appears. Those lines drive the work in B5.
| Step | What to confirm |
|---|---|
| Step 1 of 6 - Authenticating to Azure | Tenant matches UnitedLex and 4 subscriptions are in scope |
| Step 2 of 6 - Discovering patch groups | Patch groups discovered, and any groups flagged with failed, deferred, or cancelled runs |
| Step 3 of 6 - Reconciling machines and runs | Machine runs reconciled, and the count of runs needing attention |
| Step 4 of 6 - Pulling installed-patch detail | Installed-patch row count |
| Step 5 of 6 - Enriching patches with CVEs | Enrichment coverage and any API warnings |
| Step 6 of 6 - Writing report artifacts | Three artifacts written |
CVE enrichment in Step 5 is the longest phase and processes Linux packages in throttled, cached batches. Allow it to finish.
B3. Copy the ticket notes block
Below the TICKET NOTES - COPY BELOW THIS LINE divider, the terminal prints a structured block covering Scope, Results, Output files, and Attention Required.
Copy the whole block into the ticket as an internal note. It is the internal record of the run.
B4. Open the outputs in Notepad
notepad .\aum_postpatch_YYYYMMDD_HHMM.email.md
Substitute the actual filename. Three artifacts are produced by each run.
| Artifact | Purpose |
|---|---|
.email.md |
The client-facing email. Opened in Notepad for review and delivery. |
.csv |
The patch and CVE detail attachment sent to the client. One row per unique patch-to-CVE pairing, with columns for MachineName, MachineResourceId, OS, DistroFamily, PatchGroup, PatchName, KBNumber, Version, Classification, InstallTime, PatchGroupSubscription, CVE, Severity, and CVSS. |
.log |
The internal run log. Not sent to the client. Retained for troubleshooting. |
B5. Identify machines that need attention
Read the Machines needing attention list in the email alongside the Attention Required block captured in B3. The following conditions need action.
| Condition | What it means |
|---|---|
| No install record - Failed | The machine did not report an installation result. The most common failure. |
| Incomplete - N still pending (Rebooted) | The machine patched and rebooted but still has updates outstanding. |
| Window exceeded | The run did not finish inside the window duration. |
| Reboot issue | The machine did not reboot as required, leaving updates pending. |
| Success rate below 100 percent for a group | One or more machines in that group did not complete successfully. |
If a group reports a 0 percent success rate with every machine failing, that points to a group-level or platform-level cause rather than individual machines. Escalate that pattern to an Administrator rather than working the machines one at a time.
B6. Remediate patching failures
Work each failure in this order.
- Confirm the machine is powered on and reachable in the Azure portal.
- Confirm the Azure connected machine agent or VM guest agent is healthy and reporting.
- Review the Update Manager run history for the machine and record the reported error in an internal note.
- Trigger an on-demand assessment to refresh the machine's update status.
- If the approved window is still open, reboot the VM and initiate a one time update.
- Confirm the machine reports a successful installation before treating the failure as resolved.
If these steps do not resolve the failure, escalate to an Administrator. Do not troubleshoot beyond this point.
Patching after the window has closed needs Client approval first. Get that approval in writing in the ticket before installing anything.
B7. Amend the email if you fixed something manually
If failures were remediated before the window ended, update the email before sending so the client is not told a machine failed when it has in fact been resolved.
Insert wording like the following directly beneath the Machines needing attention section.
Update on machines that required attention: The machines listed above initially failed during the scheduled maintenance
run. Atmosera identified these failures during post-patch validation and
remediated them manually within the approved maintenance window. All
outstanding updates for these machines have now been installed successfully.
Please note that the CVEs associated with these manually remediated machines
are not included in the attached CSV. The report reflects the results of the
scheduled patch run, and because these machines failed during that run and
required manual intervention, their patch-to-CVE detail was not captured in
the dataset. The updates themselves have been applied.
Adjust the wording to match the machines and circumstances. Do not delete the original failure entries. The record of what happened stays, with the remediation stated alongside it.
B8. Check the data quality notes
The email includes a Data quality notes section. These notes affect how complete the report is, not whether it is correct. None of them are a reason to hold the report back.
| Note | What it means |
|---|---|
| A Security or Critical KB could not be mapped to any CVE | Microsoft has not published a CVE mapping for that KB, or it falls outside the period searched. Record it in an internal note. If the same KB appears across several runs, raise it with SecOps. |
| Ubuntu CVE API returned 429 Too Many Requests | The public API is throttling. The script retries and falls back to cached data. Only the affected packages have reduced coverage. |
| Unmapped Windows rows that are not Security or Critical | Definition updates, servicing stack updates, and the Malicious Software Removal Tool correctly carry no CVE. No action needed. |
| Unrated CVEs omitted from the severity table | Not every CVE has a published severity rating. This is stated in the email and needs no action. |
B9. Send the post-patching email
- Attach the
.csvto the ticket and paste the reviewed email in as a public reply, then send. - Add an internal note listing the machines that needed attention, what you did about each one, and anything still outstanding.
- Attach the
.email.mdand.logfiles to that internal note.
B10. If a failure is still open when the window closes
If any failure cannot be remediated before the maintenance window closes, do the following.
- Leave the failure in the client email as reported. Do not amend it to suggest resolution.
- Open a follow-up ticket for the outstanding machines.
- Notify the Client if a supplemental window, a reschedule, or a waiver will be needed, and if any DR machine is affected.
Administrator Steps
Escalate to an Administrator when any of the following apply.
- An entire patch group failed.
- A machine continues to report no assessment data after a successful on-demand assessment.
- A machine repeatedly fails across consecutive maintenance windows.
- A patch group that should resolve target resources returns none.
- Remediation requires action outside the approved maintenance window.
Administrator actions.
- Review the maintenance configuration and its assignments for the affected patch group, confirming both static and dynamic scope membership resolve as intended.
- Confirm each affected VM has its patch orchestration mode set correctly for customer-managed schedules, and that any required platform safety check settings are configured as expected.
- Verify agent health on the affected machines, including the Azure connected machine agent or VM guest agent and its extension status.
- Pull the Update Manager run history and error codes for the failed runs and identify whether the cause is common across the group.
- For machines reporting outstanding updates after a reboot, determine whether a second pass is required and schedule it appropriately.
- Coordinate with the Client on any supplemental window, reschedule, or waiver.
- Escalate to Engineering or SecOps where the cause is the script, Azure platform behaviour, or a CVE enrichment source.
Engineer and SecOps Steps
Escalate to Engineering or SecOps when any of the following apply.
- Either script fails to complete, throws an unhandled error, or writes no artifacts.
- Authentication, permission, or subscription scope resolution fails.
- Required PowerShell modules cannot be installed or loaded.
- Defender for Cloud returns no vulnerability findings for machines that should have coverage.
- CVE enrichment coverage degrades persistently across multiple runs.
- A change to either script, the email template, or the repository is required.
Engineer and SecOps actions.
- Reproduce the failure using a widened horizon and capture the full
.logfile. - Validate module versions, Azure context, and effective permissions across all four subscriptions.
- For Defender for Cloud gaps, confirm vulnerability assessment coverage and agent onboarding for the affected machines.
- For enrichment gaps, confirm reachability of the MSRC CVRF API, the Ubuntu CVE API, and OSV.dev, and review the cache and fallback tier behaviour.
- Raise a Change Request with peer review for any script or repository modification. Validate the change in a non-production subscription before release.
- Communicate any change in output format to the Cloud Technician team and update this SOP accordingly.
Comments
0 comments
Please sign in to leave a comment.