Files
fleet/orbit/pkg/platform/platform_notwindows.go
Lucas Manuel Rodriguez 9aa4a3375b Remove the wmic.exe dependency in mdm_bridge table (#49296)
Resolves #34311.

It's not urgent because:
- Orbit uses a fallback mechanism to fetch the device UUID (using
SMBIOS):

https://github.com/fleetdm/fleet/blob/d3092bbc640ebd8e92c13476f0ca8772b98d425e/orbit/pkg/platform/platform_windows.go#L354-L359
- Only used by the `mdm_bridge` table implementation. Which is only used
by CIS policies (not for critical MDM functionality).

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

- [X] QA'd all new/changed functionality manually

Tested on both a Windows 11 VM with 25H2 and real Windows 11 device with
23H2. The extracted UUID matches the UUID reported by osquery.

## fleetd/orbit/Fleet Desktop

- [X] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [X] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [X] Verified that fleetd runs on macOS, Linux and Windows
- [X] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
- Updated Windows device identification to obtain the system UUID using
COM-based WMI querying instead of relying on the deprecated WMIC
utility.
- Removed the WMIC dependency from the MDM bridge table implementation.
- Improved cross-platform UUID handling by removing unused non-Windows
UUID placeholder logic and related constants.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-16 11:42:28 -03:00

118 lines
3.1 KiB
Go

//go:build !windows
// +build !windows
package platform
import (
"errors"
"fmt"
"os"
"strings"
"github.com/fleetdm/fleet/v4/orbit/pkg/constant"
gopsutil_process "github.com/shirou/gopsutil/v4/process"
)
// ChmodRestrictFile sets the appropriate permissions on a file so it can not be read by everyone
// On POSIX this is a normal chmod call.
func ChmodRestrictFile(path string) error {
if err := os.Chmod(path, constant.DefaultFileMode); err != nil {
return fmt.Errorf("chmod restrict file: %w", err)
}
return nil
}
// ChmodExecutableDirectory sets the appropriate permissions on an executable
// file. On POSIX this is a normal chmod call.
func ChmodExecutableDirectory(path string) error {
if err := os.Chmod(path, constant.DefaultDirMode); err != nil {
return fmt.Errorf("chmod executable directory: %w", err)
}
return nil
}
// ChmodExecutable sets the appropriate permissions on the parent directory of
// an executable file. On POSIX this is a regular chmod call.
func ChmodExecutable(path string) error {
if err := os.Chmod(path, constant.DefaultExecutableMode); err != nil {
return fmt.Errorf("chmod executable: %w", err)
}
return nil
}
// SignalProcessBeforeTerminate just force terminate the target process
// Signaling the child process before termination is not supported on non-windows OSes
func SignalProcessBeforeTerminate(processName string) error {
if processName == "" {
return errors.New("processName should not be empty")
}
if err := killProcessByName(constant.DesktopAppExecName); err != nil && !errors.Is(err, ErrProcessNotFound) {
return fmt.Errorf("There was an error kill target process %s: %w", processName, err)
}
return nil
}
// GetProcessesByName gets all running processes by its name.
// Returns ErrProcessNotFound if the process was not found running.
func GetProcessesByName(name string) ([]*gopsutil_process.Process, error) {
if name == "" {
return nil, errors.New("process name should not be empty")
}
processes, err := gopsutil_process.Processes()
if err != nil {
return nil, err
}
var foundProcesses []*gopsutil_process.Process
for _, process := range processes {
processName, err := process.Name()
if err != nil {
// No need to print errors here as this method might file for system processes
continue
}
if strings.HasPrefix(processName, name) {
foundProcesses = append(foundProcesses, process)
break
}
}
if len(foundProcesses) == 0 {
return nil, ErrProcessNotFound
}
return foundProcesses, nil
}
// RunUpdateQuirks is a no-op on non-windows platforms
func PreUpdateQuirks() {
}
// IsInvalidReparsePoint is a no-op on non-windows platforms
func IsInvalidReparsePoint(err error) bool {
return false
}
// killProcessByName kills a single process by its name.
func killProcessByName(name string) error {
if name == "" {
return errors.New("process name should not be empty")
}
foundProcesses, err := GetProcessesByName(name)
if err != nil {
return fmt.Errorf("get process: %w", err)
}
for _, foundProcess := range foundProcesses {
if err := foundProcess.Kill(); err != nil {
return fmt.Errorf("kill process %d: %w", foundProcess.Pid, err)
}
}
return nil
}