Have a real fixed HostID on Linux

On Linux, most golang programs do not run as root (or at least, they should not),
by default, the kernels uses strict permissions, so most userland programs cannot
read `/sys/class/dmi/id/product_uuid`. However, programs such as Consul are relying
on it to get fixed IDs, instead they have a different ID on each boot.

We propose to use `/etc/machine-id` as fallback https://www.freedesktop.org/software/systemd/man/machine-id.html

In order to fix this, this patch does the following:
 - if `/sys/class/dmi/id/product_uuid` can be read, use it for HostID
 - else if `/etc/machine-id` exists and has 32 chars, use it and add '-' to have the same format as product_uuid
 - finally, if notthing works, use the `kernel.random.boot_id`

This will greatly increase the number of programs having correct behaviour when
those rely on having a fixed HostID.

This will fix the following issues:
 - https://github.com/shirou/gopsutil/issues/350
 - https://github.com/hashicorp/consul/issues/4741
pull/603/head
Pierre Souchay 6 years ago
parent 4254ce2081
commit be2b25a7c6

@ -73,7 +73,9 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
}
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
machineID := common.HostEtc("machine-id")
switch {
// When not running as root, lib cannot read the value
case common.PathExists(sysProductUUID):
lines, err := common.ReadLines(sysProductUUID)
if err == nil && len(lines) > 0 && lines[0] != "" {
@ -81,6 +83,14 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
break
}
fallthrough
case common.PathExists(machineID):
lines, err := common.ReadLines(machineID)
if err == nil && len(lines) > 0 && len(lines[0]) == 32 {
st := lines[0]
ret.HostID = fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32])
break
}
fallthrough
default:
values, err := common.DoSysctrl("kernel.random.boot_id")
if err == nil && len(values) == 1 && values[0] != "" {

Loading…
Cancel
Save