Skip to content

Conversation

@sigilioso
Copy link
Contributor

@sigilioso sigilioso commented Oct 29, 2025

This PR adds support for obtaining the machine identifier on Windows systems by reading the MachineGuid from the Windows Registry (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography ). Previously, the machine ID detection only worked on Unix-based systems (Linux/macOS) by reading from /etc/machine-id or /var/lib/dbus/machine-id.

Checklist

Summary of changes

  • Windows implementation: Added resource-detection/src/system/machine_identifier/windows.rs that reads the MachineGuid from the Windows Registry path.
  • Module structure refactor: Reorganized machine identifier code into a platform-specific module structure (machine_identifier/unix.rs + machine_identifier/windows.rs)
  • Improve names: Changed IdentifierProviderMachineIdMachineIdentityProvider.
  • System Resource Detector unit tests: involving a little refactor to mock the utilities to get the host name and the instance id.

Dependencies

  • Added winreg: Windows-specific dependency for registry access
  • Added rstest to workspace dependencies.
  • Updated various transitive dependencies and THIRD_PARTY_NOTICES.md

Manual testing

  • The approach has been validated in a Windows 11 arm virtual machine (the MachineGuid was read from the registry as expected).

@sigilioso sigilioso force-pushed the feat/windows-machine-guid branch 3 times, most recently from 0caa201 to 07e9736 Compare October 29, 2025 14:24
@sigilioso sigilioso force-pushed the feat/windows-machine-guid branch from 07e9736 to 1bb265c Compare October 29, 2025 14:29
@sigilioso sigilioso changed the title feat(windows): obtain machine-guid [NR-480703] (WIP) feat(windows): obtain machine-guid [NR-480703] Oct 29, 2025
@sigilioso sigilioso marked this pull request as ready for review October 29, 2025 14:59
@sigilioso sigilioso requested a review from a team as a code owner October 29, 2025 14:59
Copy link
Contributor

@danielorihuela danielorihuela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any issue. But I'm curious, the machine id is unique for each machine, right? Have you tried out if the same result is returned? Maybe it's not because of using a VM.

@sigilioso
Copy link
Contributor Author

sigilioso commented Oct 30, 2025

I don't see any issue. But I'm curious, the machine id is unique for each machine, right? Have you tried out if the same result is returned? Maybe it's not because of using a VM.

Apparently, the MachineGuid is unique for each Windows installation which means that it will be unique unless an image that wasn't generalized with sysprep is used. I simply tried it in a single VM.

@sigilioso sigilioso requested review from a team and danielorihuela October 30, 2025 08:30
@sigilioso
Copy link
Contributor Author

We'll wait for #1752 to merge this.

@danielorihuela
Copy link
Contributor

I don't see any issue. But I'm curious, the machine id is unique for each machine, right? Have you tried out if the same result is returned? Maybe it's not because of using a VM.

Apparently, the MachineGuid is unique for each Windows installation which means that it will be unique unless an image that wasn't generalized with sysprep is used. Simply tried it in a VM.

Okey. I thought this was the MAC and that it should be the same in unix, windows, etc. I see now that is a unique UUID that can be changed. Thanks!!!

Copy link
Contributor

@DavSanchez DavSanchez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have some nits due to not knowing much about what's happening in the unsafe blocks, the syscalls etc. If I get some new insights when I advance in the Windows process management I'll open PRs with proposals. Thanks! 👌

}

// Allocate buffer and read the actual value
let mut buffer: Vec<u16> = vec![0; (data_size / 2) as usize];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah didn't know the macro allowed you to set the capacity 👌

Comment on lines +10 to +11
#[derive(Default)]
pub struct MachineIdentityProvider {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't need Default due to constraints or something I'd leave it. We can create a value of this (zero-sized) type just with let x = MachineIdentityProvider;.

Suggested change
#[derive(Default)]
pub struct MachineIdentityProvider {}
pub struct MachineIdentityProvider;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true, however, the interface that both unix and windows implementations satisfy include the default.

We could add some abstractions to overcome it, but I'm not sure if it is worth it.

Comment on lines +34 to +36
unsafe {
// Open the registry key
let mut registry_key: *mut std::ffi::c_void = std::ptr::null_mut();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😬

Comment on lines +112 to +122
unsafe fn close_registry_key(hkey: *mut std::ffi::c_void) -> Result<(), SystemDetectorError> {
unsafe {
let result = RegCloseKey(hkey);
if result != ERROR_SUCCESS {
return Err(SystemDetectorError::MachineIDError(format!(
"failed to close the registry key: error code {result}"
)));
}
Ok(())
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a thing that can cause weird behavior if we forget to perform it? If so, we should probably tie it to a value lifecycle to ensure it gets called always (like impl Drop, though that would be at the expense of error handling) or something, particularly if we are going to reuse this code.

Just out of curiosity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not completely sure of the consequences of not-closing. If we finally refactor the code (note that everything is private as of now) to make it reusable let's take it into account. For now the helper is merely mapping the error in case of failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants