From 4b1e7a6f16663b9e123aaf8c7dd854039e6c1726 Mon Sep 17 00:00:00 2001 From: andig Date: Mon, 26 Sep 2022 23:18:08 +0200 Subject: [PATCH] Replace machine-id errors by configuration hint (#4591) --- cmd/setup.go | 6 +++ core/site.go | 2 +- go.mod | 3 +- go.sum | 2 - hems/ocpp/ocpp.go | 4 +- hems/semp/semp.go | 4 +- util/helper.go | 2 +- util/machine/machine.go | 66 +++++++++++++++++++++++ util/machine/machine_test.go | 22 ++++++++ util/telemetry/{charging.go => charge.go} | 25 +++++---- 10 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 util/machine/machine.go create mode 100644 util/machine/machine_test.go rename util/telemetry/{charging.go => charge.go} (79%) diff --git a/cmd/setup.go b/cmd/setup.go index b1dcfd1a7..a4cbd5c37 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -20,6 +20,7 @@ import ( "github.com/evcc-io/evcc/server" "github.com/evcc-io/evcc/tariff" "github.com/evcc-io/evcc/util" + "github.com/evcc-io/evcc/util/machine" "github.com/evcc-io/evcc/util/pipe" "github.com/evcc-io/evcc/util/sponsor" "github.com/evcc-io/evcc/util/telemetry" @@ -54,6 +55,11 @@ func loadConfigFile(conf *config) error { } func configureEnvironment(conf config) (err error) { + // setup machine id + if conf.Plant != "" { + err = machine.CustomID(conf.Plant) + } + // setup sponsorship if conf.SponsorToken != "" { err = sponsor.ConfigureSponsorship(conf.SponsorToken) diff --git a/core/site.go b/core/site.go index 092962742..dc976d5bf 100644 --- a/core/site.go +++ b/core/site.go @@ -469,7 +469,7 @@ func (site *Site) update(lp Updater) { // update savings and aggregate telemetry // TODO: use energy instead of current power for better results deltaCharged, deltaSelf := site.savings.Update(site, site.gridPower, site.pvPower, site.batteryPower, totalChargePower) - if telemetry.Enabled && totalChargePower > standbyPower { + if telemetry.Enabled() && totalChargePower > standbyPower { go telemetry.UpdateChargeProgress(site.log, totalChargePower, deltaCharged, deltaSelf) } } diff --git a/go.mod b/go.mod index cf77d4e69..298082a0f 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/containrrr/shoutrrr v0.6.1 github.com/coreos/go-oidc/v3 v3.3.0 github.com/deepmap/oapi-codegen v1.11.0 + github.com/denisbrodbeck/machineid v1.0.1 github.com/dmarkham/enumer v1.5.6 github.com/dustin/go-humanize v1.0.0 github.com/dylanmei/iso8601 v0.1.0 @@ -62,7 +63,6 @@ require ( github.com/nicksnyder/go-i18n/v2 v2.2.0 github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c github.com/olekukonko/tablewriter v0.0.5 - github.com/panta/machineid v1.0.1 github.com/philippseith/signalr v0.6.1-0.20220829124759-bd5ffb679356 github.com/prometheus/client_golang v1.13.0 github.com/prometheus/common v0.37.0 @@ -101,7 +101,6 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/denisbrodbeck/machineid v1.0.1 // indirect github.com/fatih/color v1.13.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect diff --git a/go.sum b/go.sum index 4962a29e1..6df5528ee 100644 --- a/go.sum +++ b/go.sum @@ -693,8 +693,6 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/panta/machineid v1.0.1 h1:IUIF47trYWR813A3cO/MnTEpesPFOhvejyauCGh1KI0= -github.com/panta/machineid v1.0.1/go.mod h1:JXdlT3pyUqvDz7Pf1VeU2hRa1DIfOu0zBrj+xSvVbDg= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/name v1.0.0/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM= github.com/pascaldekloe/name v1.0.1 h1:9lnXOHeqeHHnWLbKfH6X98+4+ETVqFqxN09UXSjcMb0= diff --git a/hems/ocpp/ocpp.go b/hems/ocpp/ocpp.go index 520ea77b0..8bb4d27ac 100644 --- a/hems/ocpp/ocpp.go +++ b/hems/ocpp/ocpp.go @@ -10,11 +10,11 @@ import ( "github.com/evcc-io/evcc/core/site" "github.com/evcc-io/evcc/hems/ocpp/profile" "github.com/evcc-io/evcc/util" + "github.com/evcc-io/evcc/util/machine" ocpp16 "github.com/lorenzodonini/ocpp-go/ocpp1.6" ocppcore "github.com/lorenzodonini/ocpp-go/ocpp1.6/core" "github.com/lorenzodonini/ocpp-go/ws" - "github.com/panta/machineid" ) // OCPP is an OCPP client @@ -40,7 +40,7 @@ func New(conf map[string]interface{}, site site.API) (*OCPP, error) { log := util.NewLogger("ocpp") if cc.StationID == "" { - id, err := machineid.ProtectedID("evcc-ocpp") + id, err := machine.ProtectedID("evcc-ocpp") if err == nil { cc.StationID = fmt.Sprintf("evcc-%s", strings.ToLower(id)) } else { diff --git a/hems/semp/semp.go b/hems/semp/semp.go index 333d183ef..3217fd901 100644 --- a/hems/semp/semp.go +++ b/hems/semp/semp.go @@ -17,10 +17,10 @@ import ( "github.com/evcc-io/evcc/core/site" "github.com/evcc-io/evcc/server" "github.com/evcc-io/evcc/util" + "github.com/evcc-io/evcc/util/machine" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/koron/go-ssdp" - "github.com/panta/machineid" ) const ( @@ -344,7 +344,7 @@ func (s *SEMP) serialNumber(id int) string { func UniqueDeviceID() ([]byte, error) { bytes := 6 - mid, err := machineid.ProtectedID("evcc-semp") + mid, err := machine.ProtectedID("evcc-semp") if err != nil { return nil, err } diff --git a/util/helper.go b/util/helper.go index b9754dc98..14158a488 100644 --- a/util/helper.go +++ b/util/helper.go @@ -4,7 +4,7 @@ import ( "math/rand" ) -// RandomString creates random string of N integers +// RandomString creates random string of N characters func RandomString(n int) string { letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") s := make([]rune, n) diff --git a/util/machine/machine.go b/util/machine/machine.go new file mode 100644 index 000000000..761dd6195 --- /dev/null +++ b/util/machine/machine.go @@ -0,0 +1,66 @@ +package machine + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "fmt" + "strings" + + "github.com/evcc-io/evcc/util" + + "github.com/denisbrodbeck/machineid" +) + +var id string + +// CustomID sets the machine id to a custom value +func CustomID(cid string) error { + if id != "" { + panic("machine id already generated") + } + + cid = strings.TrimSpace(cid) + if l := len(cid); l != 32 { + return fmt.Errorf("expected 32 characters machine id, got %d", l) + } + + id = cid + + return nil +} + +// ID returns the platform specific machine id of the current host OS. +// If ID cannot be generated, a random value is suggested. +func ID() (string, error) { + if id == "" { + var err error + if id, err = machineid.ID(); err != nil { + rnd := util.RandomString(512) + mac := hmac.New(sha256.New, []byte(rnd)) + rid := hex.EncodeToString(mac.Sum(nil)) + + return "", fmt.Errorf("could not get %w; for manual configuration use plant: %s", err, rid) + } + } + + return id, nil +} + +// ProtectedID returns a hashed version of the machine id +// using a fixed, application-specific key. +func ProtectedID(key string) (string, error) { + id, err := machineid.ID() + if err != nil { + return id, err + } + + return protect(key, id), nil +} + +// protect calculates HMAC-SHA256 of the id, keyed by key and returns a hex-encoded string +func protect(key, id string) string { + mac := hmac.New(sha256.New, []byte(id)) + mac.Write([]byte(key)) + return hex.EncodeToString(mac.Sum(nil)) +} diff --git a/util/machine/machine_test.go b/util/machine/machine_test.go new file mode 100644 index 000000000..43a852af7 --- /dev/null +++ b/util/machine/machine_test.go @@ -0,0 +1,22 @@ +package machine + +import ( + "testing" + + "github.com/denisbrodbeck/machineid" +) + +func TestProtectedMachineId(t *testing.T) { + const key = "foo" + + if mid, err := machineid.ProtectedID(key); err == nil { + id, err := ProtectedID(key) + if err != nil { + t.Error(err) + } + + if mid != id { + t.Errorf("machine id mismatch. expected %s, got %s", mid, id) + } + } +} diff --git a/util/telemetry/charging.go b/util/telemetry/charge.go similarity index 79% rename from util/telemetry/charging.go rename to util/telemetry/charge.go index 88e889ad4..277511902 100644 --- a/util/telemetry/charging.go +++ b/util/telemetry/charge.go @@ -6,30 +6,33 @@ import ( "net/http" "github.com/evcc-io/evcc/util" + "github.com/evcc-io/evcc/util/machine" "github.com/evcc-io/evcc/util/request" "github.com/evcc-io/evcc/util/sponsor" - "github.com/panta/machineid" ) const api = "https://api.evcc.io" -var ( - Enabled bool - instanceID string -) +var instanceID string -func Create(token, instance string) error { +func Enabled() bool { + return instanceID != "" +} + +func Create(token, machineID string) error { if token == "" { return errors.New("telemetry requires sponsorship") } - Enabled = true - instanceID = instance - - if mid, err := machineid.ProtectedID("evcc-api"); err == nil && instanceID == "" { - instanceID = mid + if machineID == "" { + var err error + if machineID, err = machine.ProtectedID("evcc-api"); err != nil { + return err + } } + instanceID = machineID + return nil }