Feature: [Ubuntu, no-CVM] CVM machines to not get UEFI and kek certificate updates#356
Feature: [Ubuntu, no-CVM] CVM machines to not get UEFI and kek certificate updates#356rane-rajasi wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces Confidential VM (CVM) detection logic to prevent UEFI/KEK certificate updates from running on Canonical CVMs, while adding unit tests to validate the new behavior.
Changes:
- Added CVM detection in
EnvLayerusing Azure IMDS and an FDE-based detection script. - Updated
PatchInstallerto skip certificate updates when a CVM is detected. - Added/updated unit tests covering CVM detection and the certificate-update skip path.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/core/src/core_logic/PatchInstaller.py | Skips update_certs() when CVM detection indicates the VM is confidential. |
| src/core/src/bootstrap/EnvLayer.py | Implements CVM detection via IMDS and FDE-based script execution. |
| src/core/src/bootstrap/Constants.py | Adds a constant path for the CVM detection script. |
| src/core/tests/Test_PatchInstaller.py | Adds a test ensuring certificate updates are skipped on confidential VMs. |
| src/core/tests/Test_EnvLayer.py | Adds tests for IMDS/FDE CVM detection and call ordering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #356 +/- ##
==========================================
+ Coverage 93.99% 94.04% +0.04%
==========================================
Files 107 107
Lines 19810 19941 +131
==========================================
+ Hits 18621 18753 +132
+ Misses 1189 1188 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
|
||
| is_confidential_vm, detection_details = self.detect_confidential_vm_by_imds() | ||
| if is_confidential_vm: | ||
| return True, detection_details |
There was a problem hiding this comment.
Why can't we just return is_confidential_vm here?
There was a problem hiding this comment.
Changed to return is_confidential_vm
| """Runs the FDE-based CVM detection script and returns whether it detected a Confidential VM.""" | ||
| script_path = Constants.AzGPSPaths.DETECT_CVM | ||
| command_output = str() | ||
| detection_script = """#!/usr/bin/env bash |
There was a problem hiding this comment.
Do we have anywhere else we do something like this? Is there no way that the script could be put in its own file and then run? It feels wrong to hard code a script like this.
| def detect_confidential_vm_by_imds(self): | ||
| # type: () -> tuple | ||
| """Queries Azure IMDS and returns whether the VM reports ConfidentialVM security type.""" | ||
| command = 'curl -s --connect-timeout 2 --max-time 2 -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2025-04-07"' |
There was a problem hiding this comment.
Is there a chance this IP address changes and could be spoofed/taken by a malicious actor?
There was a problem hiding this comment.
I don't have much insight on this one, simply used the command that was shared by partners to fetch from imds.
Here's Copilot's response:
✅ Short answer
No, the IP does not change
No, it cannot be externally spoofed or taken over by another tenant
🔎 Why this is safe
- Fixed, well-known platform endpoint
169.254.169.254 is a hard-coded Azure IMDS endpoint, not assigned from your VNet or subnet. [learn.microsoft.com]
It’s part of the link‑local range (169.254.0.0/16), reserved for host-local communication. [simonpainter.com]
➡️ This means:
It is not customer-controlled
It is not dynamically allocated
Azure guarantees its availability and consistency
- Not reachable from outside the VM
The endpoint is non-routable and only accessible from within the VM [learn.microsoft.com]
Traffic to IMDS never leaves the host [learn.microsoft.com]
➡️ So:
No external attacker can “impersonate” this endpoint over the network
It’s effectively a host-side service exposed into the VM
- Platform-injected routing
Azure automatically injects a route to 169.254.169.254 via the VM’s primary NIC (not via your VNet config) [simonpainter.com]
➡️ This prevents:
DNS spoofing
Route hijacking from within normal networking config
The only realistic risk is:
If an attacker already has root/admin access inside the VM, they could:
Intercept traffic locally
Modify iptables / routing
Run a fake service on that IP
✅ But:
At that point, the VM is already compromised
This is not specific to IMDS (applies to any local endpoint)
💡 Best-practice statement
The IMDS endpoint (169.254.169.254) is a well-known, platform-defined link-local address that is not part of the customer-controlled network and does not change across deployments. It is non-routable and only accessible from within the VM, with traffic handled entirely within the Azure host fabric.
This prevents external spoofing or takeover by other tenants. The only theoretical risk would require local root-level compromise of the VM, in which case any local endpoint (not just IMDS) could be intercepted.
These changes are for Canonical CVMs, the ask is, Canonical CVMs should not get UEFI and kek certificate updates.
There are 2 ways (imds and fde) of determining if a VM is a CVM, we are checking using both mechanisms and only applying certificate updates if both of these compute to false.
In VM tests:
1.core.log
1.status.txt