-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathsecureboot.go
More file actions
84 lines (71 loc) · 2.25 KB
/
secureboot.go
File metadata and controls
84 lines (71 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright Mondoo, Inc. 2024, 2026
// SPDX-License-Identifier: BUSL-1.1
package resources
import (
"sync"
"github.com/spf13/afero"
"go.mondoo.com/mql/v13/providers/os/connection/shared"
)
// EFI variable GUID for global Secure Boot variables.
const efiGlobalVariable = "8be4df61-93ca-11d2-aa0d-00e098032b8c"
type mqlMachineSecurebootInternal struct {
once sync.Once
cacheEfi bool
cacheEnabled bool
cacheSetupMode bool
fetchErr error
}
func (s *mqlMachineSecureboot) id() (string, error) {
return "machine.secureboot", nil
}
// fetchStatus reads the EFI firmware variables once and caches the result.
func (s *mqlMachineSecureboot) fetchStatus() error {
s.once.Do(func() {
conn := s.MqlRuntime.Connection.(shared.Connection)
fs := conn.FileSystem()
// Check if the system is booted in EFI mode by looking for /sys/firmware/efi.
_, err := fs.Stat("/sys/firmware/efi")
if err != nil {
// No EFI directory means legacy BIOS boot — no Secure Boot possible.
return
}
s.cacheEfi = true
s.cacheEnabled = readEfiVarBool(fs, "SecureBoot-"+efiGlobalVariable)
s.cacheSetupMode = readEfiVarBool(fs, "SetupMode-"+efiGlobalVariable)
})
return s.fetchErr
}
// readEfiVarBool reads an EFI variable from /sys/firmware/efi/efivars/ and
// returns true if its data byte is 1. EFI variable files contain a 4-byte
// attribute header followed by the variable data.
func readEfiVarBool(fs afero.Fs, name string) bool {
data, err := afero.ReadFile(fs, "/sys/firmware/efi/efivars/"+name)
if err != nil {
return false
}
// Must have at least 4 bytes of attributes + 1 byte of data.
if len(data) < 5 {
return false
}
// The data portion starts after the 4-byte EFI variable attributes header.
// For SecureBoot/SetupMode the data is a single uint8: 1 = on, 0 = off.
return data[4] == 1
}
func (s *mqlMachineSecureboot) efi() (bool, error) {
if err := s.fetchStatus(); err != nil {
return false, err
}
return s.cacheEfi, nil
}
func (s *mqlMachineSecureboot) enabled() (bool, error) {
if err := s.fetchStatus(); err != nil {
return false, err
}
return s.cacheEnabled, nil
}
func (s *mqlMachineSecureboot) setupMode() (bool, error) {
if err := s.fetchStatus(); err != nil {
return false, err
}
return s.cacheSetupMode, nil
}