Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v15] devicetrust: don't invoke powershell when reading system information #50455

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ require (
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb
github.com/vulcand/predicate v1.2.0 // replaced
github.com/xanzy/go-gitlab v0.103.0
github.com/yusufpapurcu/wmi v1.2.4
go.etcd.io/etcd/api/v3 v3.5.12
go.etcd.io/etcd/client/v3 v3.5.12
go.mongodb.org/mongo-driver v1.14.0
Expand Down Expand Up @@ -510,7 +511,6 @@ require (
github.com/xlab/treeprint v1.2.0 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
github.com/yuin/gopher-lua v1.1.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zeebo/errs v1.3.0 // indirect
github.com/zeebo/xxh3 v1.0.2 // indirect
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300 // indirect
Expand Down
131 changes: 58 additions & 73 deletions lib/devicetrust/native/device_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@
package native

import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"os"
"os/exec"
"os/user"
"strconv"
"time"

"github.com/google/go-attestation/attest"
"github.com/gravitational/trace"
log "github.com/sirupsen/logrus"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sync/errgroup"
"golang.org/x/sys/windows"
"google.golang.org/protobuf/types/known/timestamppb"
Expand Down Expand Up @@ -78,106 +79,90 @@ func handleTPMActivateCredential(encryptedCredential, encryptedCredentialSecret
return windowsDevice.handleTPMActivateCredential(encryptedCredential, encryptedCredentialSecret)
}

// getDeviceSerial returns the serial number of the device using PowerShell to
// grab the correct WMI objects. Getting it without calling into PS is possible,
// but requires interfacing with the ancient Win32 COM APIs.
func getDeviceSerial() (string, error) {
cmd := exec.Command(
"powershell",
"-NoProfile",
"Get-WmiObject Win32_BIOS | Select -ExpandProperty SerialNumber",
)
// ThinkPad P P14s:
// PS > Get-WmiObject Win32_BIOS | Select -ExpandProperty SerialNumber
// PF47WND6
out, err := cmd.Output()
if err != nil {

type Win32_BIOS struct {
SerialNumber string
}

var bios []Win32_BIOS
query := wmi.CreateQuery(&bios, "")
if err := wmi.Query(query, &bios); err != nil {
return "", trace.Wrap(err)
}
return string(bytes.TrimSpace(out)), nil

if len(bios) == 0 {
return "", trace.BadParameter("could not read serial number from Win32_BIOS")
}

return bios[0].SerialNumber, nil
}

func getReportedAssetTag() (string, error) {
cmd := exec.Command(
"powershell",
"-NoProfile",
"Get-WmiObject Win32_SystemEnclosure | Select -ExpandProperty SMBIOSAssetTag",
)
// ThinkPad P P14s:
// PS > Get-WmiObject Win32_SystemEnclosure | Select -ExpandProperty SMBIOSAssetTag
// winaia_1337
out, err := cmd.Output()
if err != nil {

type Win32_SystemEnclosure struct {
SMBIOSAssetTag string
}

var system []Win32_SystemEnclosure
query := wmi.CreateQuery(&system, "")
if err := wmi.Query(query, &system); err != nil {
return "", trace.Wrap(err)
}
return string(bytes.TrimSpace(out)), nil

if len(system) == 0 {
return "", trace.BadParameter("could not read asset tag from Win32_SystemEnclosure")
}

return system[0].SMBIOSAssetTag, nil
}

func getDeviceModel() (string, error) {
cmd := exec.Command(
"powershell",
"-NoProfile",
"Get-WmiObject Win32_ComputerSystem | Select -ExpandProperty Model",
)
// ThinkPad P P14s:
// PS> Get-WmiObject Win32_ComputerSystem | Select -ExpandProperty Model
// 21J50013US
out, err := cmd.Output()
if err != nil {

type Win32_ComputerSystem struct {
Model string
}
var cs []Win32_ComputerSystem
query := wmi.CreateQuery(&cs, "")
if err := wmi.Query(query, &cs); err != nil {
return "", trace.Wrap(err)
}
return string(bytes.TrimSpace(out)), nil

if len(cs) == 0 {
return "", trace.BadParameter("could not read model from Win32_ComputerSystem")
}

return cs[0].Model, nil
}

func getDeviceBaseBoardSerial() (string, error) {
cmd := exec.Command(
"powershell",
"-NoProfile",
"Get-WmiObject Win32_BaseBoard | Select -ExpandProperty SerialNumber",
)
// ThinkPad P P14s:
// PS> Get-WmiObject Win32_BaseBoard | Select -ExpandProperty SerialNumber
// L1HF2CM03ZT
out, err := cmd.Output()
if err != nil {
return "", trace.Wrap(err)
}

return string(bytes.TrimSpace(out)), nil
}

func getOSVersion() (string, error) {
cmd := exec.Command(
"powershell",
"-NoProfile",
"Get-WmiObject Win32_OperatingSystem | Select -ExpandProperty Version",
)
// ThinkPad P P14s:
// PS> Get-WmiObject Win32_OperatingSystem | Select -ExpandProperty Version
// 10.0.22621
out, err := cmd.Output()
if err != nil {
type Win32_BaseBoard struct {
SerialNumber string
}
var bb []Win32_BaseBoard
query := wmi.CreateQuery(&bb, "")
if err := wmi.Query(query, &bb); err != nil {
return "", trace.Wrap(err)
}

return string(bytes.TrimSpace(out)), nil
}

func getOSBuildNumber() (string, error) {
cmd := exec.Command(
"powershell",
"-NoProfile",
"Get-WmiObject Win32_OperatingSystem | Select -ExpandProperty BuildNumber",
)
// ThinkPad P P14s:
// PS> Get-WmiObject Win32_OperatingSystem | Select -ExpandProperty BuildNumber
// 22621
out, err := cmd.Output()
if err != nil {
return "", trace.Wrap(err)
if len(bb) == 0 {
return "", trace.BadParameter("could not read serial from Win32_BaseBoard")
}

return string(bytes.TrimSpace(out)), nil
return bb[0].SerialNumber, nil
}

func collectDeviceData(_ CollectDataMode) (*devicepb.DeviceCollectedData, error) {
Expand All @@ -188,15 +173,13 @@ func collectDeviceData(_ CollectDataMode) (*devicepb.DeviceCollectedData, error)
g.SetLimit(groupLimit)

// Run exec-ed commands concurrently.
var systemSerial, baseBoardSerial, reportedAssetTag, model, osVersion, osBuildNumber string
var systemSerial, baseBoardSerial, reportedAssetTag, model string
for _, spec := range []struct {
fn func() (string, error)
out *string
desc string
}{
{fn: getDeviceModel, out: &model, desc: "device model"},
{fn: getOSVersion, out: &osVersion, desc: "os version"},
{fn: getOSBuildNumber, out: &osBuildNumber, desc: "os build number"},
{fn: getDeviceSerial, out: &systemSerial, desc: "system serial"},
{fn: getDeviceBaseBoardSerial, out: &baseBoardSerial, desc: "base board serial"},
{fn: getReportedAssetTag, out: &reportedAssetTag, desc: "reported asset tag"},
Expand All @@ -214,6 +197,8 @@ func collectDeviceData(_ CollectDataMode) (*devicepb.DeviceCollectedData, error)
})
}

ver := windows.RtlGetVersion()

// We want to fetch as much info as possible, so errors are ignored.
_ = g.Wait()

Expand All @@ -232,8 +217,8 @@ func collectDeviceData(_ CollectDataMode) (*devicepb.DeviceCollectedData, error)
OsType: devicepb.OSType_OS_TYPE_WINDOWS,
SerialNumber: serial,
ModelIdentifier: model,
OsVersion: osVersion,
OsBuild: osBuildNumber,
OsVersion: fmt.Sprintf("%v.%v.%v", ver.MajorVersion, ver.MinorVersion, ver.BuildNumber),
OsBuild: strconv.FormatInt(int64(ver.BuildNumber), 10),
OsUsername: u.Username,
SystemSerialNumber: systemSerial,
BaseBoardSerialNumber: baseBoardSerial,
Expand Down
Loading