153 lines
4.2 KiB
Go
153 lines
4.2 KiB
Go
// Copyright (c) 2024 Joshua Rich <joshua.rich@gmail.com>
|
|
//
|
|
// This software is released under the MIT License.
|
|
// https://opensource.org/licenses/MIT
|
|
|
|
//go:generate go run golang.org/x/tools/cmd/stringer -type=hsiResult,hsiLevel -output hsi_generated.go -linecomment
|
|
package system
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/godbus/dbus/v5"
|
|
|
|
"github.com/joshuar/go-hass-agent/internal/components/preferences"
|
|
"github.com/joshuar/go-hass-agent/internal/hass/sensor"
|
|
"github.com/joshuar/go-hass-agent/internal/linux"
|
|
"github.com/joshuar/go-hass-agent/pkg/linux/dbusx"
|
|
)
|
|
|
|
const (
|
|
fwupdmgrWorkerID = "fwupdmgr_worker"
|
|
fwupdmgrPreferencesID = infoWorkerPreferencesID
|
|
|
|
fwupdInterface = "org.freedesktop.fwupd"
|
|
hostSecurityAttrsMethod = "GetHostSecurityAttrs"
|
|
hostSecurityIDProp = "HostSecurityId"
|
|
)
|
|
|
|
const (
|
|
ResultUnknown hsiResult = iota // Not Known
|
|
ResultEnabled // Enabled
|
|
ResultNotEnabled // Not Enabled
|
|
ResultValid // Valid
|
|
ResultNotValid // Not Valid
|
|
ResultLocked // Locked
|
|
ResultNotLocked // Not Locked
|
|
ResultEncrypted // Encrypted
|
|
ResultNotEncrypted // Not Encrypted
|
|
ResultTainted // Tainted
|
|
ResultNotTainted // Not Tainted
|
|
ResultFound // Found
|
|
ResultNotFound // Not Found
|
|
ResultSupported // Supported
|
|
ResultNotSupported // Not Supported
|
|
|
|
)
|
|
|
|
type hsiResult uint32
|
|
|
|
const (
|
|
hsi0 hsiLevel = iota // HSI:0 (Insecure State)
|
|
hsi1 // HSI:1 (Critical State)
|
|
hsi2 // HSI:2 (Risky State)
|
|
hsi3 // HSI:3 (Protected State)
|
|
hsi4 // HSI:4 (Secure State)
|
|
hsi5 // HSI:5 (Secure Proven State)
|
|
)
|
|
|
|
type hsiLevel uint32
|
|
|
|
type fwupdWorker struct {
|
|
hostSecurityAttrs *dbusx.Data[[]map[string]dbus.Variant]
|
|
hostSecurityID *dbusx.Property[string]
|
|
}
|
|
|
|
//nolint:errcheck
|
|
func (w *fwupdWorker) Sensors(ctx context.Context) ([]sensor.Entity, error) {
|
|
props, err := w.hostSecurityAttrs.Fetch(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not retrieve security properties from fwupd: %w", err)
|
|
}
|
|
|
|
hsi, err := w.hostSecurityID.Get()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not retrieve security id from fwupd: %w", err)
|
|
}
|
|
|
|
hsiID := strings.Split(hsi, " ")
|
|
attributes := make(map[string]any)
|
|
|
|
for _, prop := range props {
|
|
var (
|
|
summary string
|
|
result hsiResult
|
|
)
|
|
|
|
if summaryRaw, found := prop["Summary"]; found {
|
|
summary, _ = dbusx.VariantToValue[string](summaryRaw)
|
|
}
|
|
|
|
if resultRaw, found := prop["HsiResult"]; found {
|
|
result, _ = dbusx.VariantToValue[hsiResult](resultRaw)
|
|
}
|
|
|
|
if summary != "" && result != ResultUnknown {
|
|
attributes[summary] = result.String()
|
|
}
|
|
}
|
|
|
|
return []sensor.Entity{
|
|
sensor.NewSensor(
|
|
sensor.WithName("Firmware Security"),
|
|
sensor.WithID("firmware_security"),
|
|
sensor.AsDiagnostic(),
|
|
sensor.WithState(
|
|
sensor.WithIcon("mdi:security"),
|
|
sensor.WithValue(hsiID[0]),
|
|
sensor.WithAttributes(attributes),
|
|
),
|
|
),
|
|
},
|
|
nil
|
|
}
|
|
|
|
func (w *fwupdWorker) PreferencesID() string {
|
|
return basePreferencesID + "." + fwupdmgrPreferencesID
|
|
}
|
|
|
|
func (w *fwupdWorker) DefaultPreferences() preferences.CommonWorkerPrefs {
|
|
return preferences.CommonWorkerPrefs{}
|
|
}
|
|
|
|
func NewfwupdWorker(ctx context.Context) (*linux.OneShotSensorWorker, error) {
|
|
fwupdWorker := &fwupdWorker{}
|
|
|
|
prefs, err := preferences.LoadWorker(ctx, fwupdWorker)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not load preferences: %w", err)
|
|
}
|
|
|
|
//nolint:nilnil
|
|
if prefs.IsDisabled() {
|
|
return nil, nil
|
|
}
|
|
|
|
bus, ok := linux.CtxGetSystemBus(ctx)
|
|
if !ok {
|
|
return nil, linux.ErrNoSystemBus
|
|
}
|
|
|
|
fwupdWorker.hostSecurityAttrs = dbusx.NewData[[]map[string]dbus.Variant](bus,
|
|
fwupdInterface, "/", fwupdInterface+"."+hostSecurityAttrsMethod)
|
|
fwupdWorker.hostSecurityID = dbusx.NewProperty[string](bus,
|
|
"/", fwupdInterface, fwupdInterface+"."+hostSecurityIDProp)
|
|
|
|
worker := linux.NewOneShotSensorWorker(fwupdmgrWorkerID)
|
|
worker.OneShotSensorType = fwupdWorker
|
|
|
|
return worker, nil
|
|
}
|