-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathmacos_filevault.go
More file actions
146 lines (128 loc) · 3.29 KB
/
macos_filevault.go
File metadata and controls
146 lines (128 loc) · 3.29 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1
package resources
import (
"errors"
"strings"
"sync"
"go.mondoo.com/mql/v13/llx"
)
type mqlMacosFilevaultInternal struct {
lock sync.Mutex
fetched bool
output string
}
func (m *mqlMacosFilevault) fetchStatus() (string, error) {
if m.fetched {
return m.output, nil
}
m.lock.Lock()
defer m.lock.Unlock()
if m.fetched {
return m.output, nil
}
res, err := NewResource(m.MqlRuntime, "command", map[string]*llx.RawData{
"command": llx.StringData("fdesetup status"),
})
if err != nil {
return "", err
}
cmd := res.(*mqlCommand)
if exit := cmd.GetExitcode(); exit.Data != 0 {
return "", errors.New("fdesetup status failed: " + cmd.GetStderr().Data)
}
// fdesetup status outputs lines like:
// "FileVault is On."
// "FileVault is Off."
// "Encryption in progress: Percent completed = 50.0"
// "Decryption in progress: Percent completed = 50.0"
output := strings.TrimSpace(cmd.GetStdout().Data)
lines := strings.SplitN(output, "\n", 2)
m.output = strings.TrimSpace(lines[0])
m.fetched = true
return m.output, nil
}
func (m *mqlMacosFilevault) status() (string, error) {
return m.fetchStatus()
}
func (m *mqlMacosFilevault) enabled() (bool, error) {
status, err := m.fetchStatus()
if err != nil {
return false, err
}
return strings.Contains(status, "FileVault is On") ||
strings.Contains(status, "Encryption in progress"), nil
}
func (m *mqlMacosFilevault) runFdesetup(subcmd string) (string, error) {
res, err := NewResource(m.MqlRuntime, "command", map[string]*llx.RawData{
"command": llx.StringData("fdesetup " + subcmd),
})
if err != nil {
return "", err
}
cmd := res.(*mqlCommand)
if exit := cmd.GetExitcode(); exit.Data != 0 {
return "", errors.New("fdesetup " + subcmd + " failed: " + cmd.GetStderr().Data)
}
return strings.TrimSpace(cmd.GetStdout().Data), nil
}
func (m *mqlMacosFilevault) hasPersonalRecoveryKey() (bool, error) {
enabled, err := m.enabled()
if err != nil {
return false, err
}
if !enabled {
return false, nil
}
// fdesetup haspersonalrecoverykey outputs "true" or "false"
output, err := m.runFdesetup("haspersonalrecoverykey")
if err != nil {
return false, err
}
return output == "true", nil
}
func (m *mqlMacosFilevault) hasInstitutionalRecoveryKey() (bool, error) {
enabled, err := m.enabled()
if err != nil {
return false, err
}
if !enabled {
return false, nil
}
// fdesetup hasinstitutionalrecoverykey outputs "true" or "false"
output, err := m.runFdesetup("hasinstitutionalrecoverykey")
if err != nil {
return false, err
}
return output == "true", nil
}
func (m *mqlMacosFilevault) users() ([]any, error) {
enabled, err := m.enabled()
if err != nil {
return nil, err
}
if !enabled {
return []any{}, nil
}
// fdesetup list outputs lines like:
// "user1,85632A00-1234-5678-ABCD-123456789ABC"
// "user2,95632A00-1234-5678-ABCD-123456789ABC"
output, err := m.runFdesetup("list")
if err != nil {
return nil, err
}
if output == "" {
return []any{}, nil
}
var users []any
for _, line := range strings.Split(output, "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
// Each line is "username,UUID" — extract the username
parts := strings.SplitN(line, ",", 2)
users = append(users, parts[0])
}
return users, nil
}