Skip to content

Commit e8c524a

Browse files
committed
Put machineID to the MAC address hasher
Signed-off-by: Akihiro Suda <[email protected]>
1 parent fbb94ed commit e8c524a

File tree

3 files changed

+134
-2
lines changed

3 files changed

+134
-2
lines changed

pkg/limayaml/defaults.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import (
88
"strconv"
99

1010
"github.com/AkihiroSuda/lima/pkg/guestagent/api"
11+
"github.com/AkihiroSuda/lima/pkg/osutil"
1112
)
1213

1314
func MACAddress(uniqueID string) string {
14-
// TODO: combine the uniqueID with the host machineID to create a globally unique hash
15-
sha := sha256.Sum256([]byte(uniqueID))
15+
sha := sha256.Sum256([]byte(osutil.MachineID() + uniqueID))
1616
// According to https://gitlab.com/wireshark/wireshark/-/blob/master/manuf
1717
// no well-known MAC addresses start with 0x22.
1818
hw := append(net.HardwareAddr{0x22}, sha[0:5]...)

pkg/osutil/machineid.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package osutil
2+
3+
import (
4+
"bytes"
5+
"encoding/xml"
6+
"fmt"
7+
"io"
8+
"os"
9+
"os/exec"
10+
"runtime"
11+
"strings"
12+
"sync"
13+
14+
"github.com/sirupsen/logrus"
15+
)
16+
17+
var (
18+
machineIDCached string
19+
machineIDOnce sync.Once
20+
)
21+
22+
func MachineID() string {
23+
machineIDOnce.Do(func() {
24+
x, err := machineID()
25+
if err == nil && x != "" {
26+
machineIDCached = x
27+
return
28+
}
29+
logrus.WithError(err).Debug("failed to get machine ID, falling back to use hostname instead")
30+
hostname, err := os.Hostname()
31+
if err != nil {
32+
panic(err)
33+
}
34+
machineIDCached = hostname
35+
})
36+
return machineIDCached
37+
}
38+
39+
func machineID() (string, error) {
40+
if runtime.GOOS == "darwin" {
41+
ioPlatformExpertDeviceCmd := exec.Command("/usr/sbin/ioreg", "-a", "-d2", "-c", "IOPlatformExpertDevice")
42+
ioPlatformExpertDevice, err := ioPlatformExpertDeviceCmd.CombinedOutput()
43+
if err != nil {
44+
return "", err
45+
}
46+
return parseIOPlatformUUIDFromIOPlatformExpertDevice(bytes.NewReader(ioPlatformExpertDevice))
47+
}
48+
49+
candidates := []string{
50+
"/etc/machine-id",
51+
"/var/lib/dbus/machine-id",
52+
// We don't use "/sys/class/dmi/id/product_uuid"
53+
}
54+
for _, f := range candidates {
55+
b, err := os.ReadFile(f)
56+
if err == nil {
57+
return strings.TrimSpace(string(b)), nil
58+
}
59+
}
60+
return "", fmt.Errorf("no machine-id found, tried %v", candidates)
61+
}
62+
63+
func parseIOPlatformUUIDFromIOPlatformExpertDevice(r io.Reader) (string, error) {
64+
d := xml.NewDecoder(r)
65+
var (
66+
elem string
67+
elemKeyCharData string
68+
)
69+
for {
70+
tok, err := d.Token()
71+
if err != nil {
72+
return "", err
73+
}
74+
switch v := tok.(type) {
75+
case xml.StartElement:
76+
elem = v.Name.Local
77+
case xml.EndElement:
78+
elem = ""
79+
if v.Name.Local != "key" {
80+
elemKeyCharData = ""
81+
}
82+
case xml.CharData:
83+
if elem == "string" && elemKeyCharData == "IOPlatformUUID" {
84+
return string(v), nil
85+
}
86+
if elem == "key" {
87+
elemKeyCharData = string(v)
88+
}
89+
}
90+
}
91+
}

pkg/osutil/machineid_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package osutil
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"gotest.tools/v3/assert"
8+
)
9+
10+
func TestMachineID(t *testing.T) {
11+
t.Log(MachineID())
12+
}
13+
14+
func TestParseIOPlatformUUIDFromIOPlatformExpertDevice(t *testing.T) {
15+
ioPlatformExpertDevice := `
16+
<?xml version="1.0" encoding="UTF-8"?>
17+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
18+
<plist version="1.0">
19+
<dict>
20+
<key>IOObjectClass</key>
21+
<string>IORegistryEntry</string>
22+
<key>IORegistryEntryChildren</key>
23+
<array>
24+
<dict>
25+
<key>foo</key>
26+
<string>foo value</string>
27+
<key>IOPlatformUUID</key>
28+
<string>1A008DA1-06E0-49AB-8EC9-88E9C85F67FB</string>
29+
<key>bar</key>
30+
<string>bar value</string>
31+
</dict>
32+
</array>
33+
<key>IORegistryEntryName</key>
34+
<string>Root</string>
35+
</dict>
36+
</plist>
37+
`
38+
got, err := parseIOPlatformUUIDFromIOPlatformExpertDevice(strings.NewReader(ioPlatformExpertDevice))
39+
assert.NilError(t, err)
40+
assert.Equal(t, "1A008DA1-06E0-49AB-8EC9-88E9C85F67FB", got)
41+
}

0 commit comments

Comments
 (0)