fleet/orbit/pkg/table/cryptsetup/parser.go
2023-11-01 20:11:35 -06:00

91 lines
2.3 KiB
Go

// based on github.com/kolide/launcher/pkg/osquery/tables
package cryptsetup
import (
"bufio"
"bytes"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
// parseStatus parses the output from `cryptsetup status`. This is a
// pretty simple key, value format, but does have a free form first
// line. It's not clear if this is going to be stable, or change
// across versions.
func parseStatus(rawdata []byte) (map[string]interface{}, error) {
var data map[string]interface{}
if len(rawdata) == 0 {
return nil, errors.New("No data")
}
scanner := bufio.NewScanner(bytes.NewReader(rawdata))
firstLine := true
for scanner.Scan() {
line := scanner.Text()
if firstLine {
var err error
data, err = parseFirstLine(line)
if err != nil {
return nil, err
}
firstLine = false
continue
}
kv := strings.SplitN(line, ": ", 2)
// blank lines, or other unexpected input can just be skipped.
if len(kv) < 2 {
continue
}
data[strings.ReplaceAll(strings.TrimSpace(kv[0]), " ", "_")] = strings.TrimSpace(kv[1])
}
return data, nil
}
// regexp for the first line of the status output.
var firstLineRegexp = regexp.MustCompile(`^(?:Device (.*) (not found))|(?:(.*?) is ([a-z]+)(?:\.| and is (in use)))`)
// parseFirstLine parses the first line of the status output. This
// appears to be a free form string indicating several pieces of
// information. It is parsed with a single regexp. (See tests for
// examples)
func parseFirstLine(line string) (map[string]interface{}, error) {
if line == "" {
return nil, errors.New("Invalid first line")
}
m := firstLineRegexp.FindAllStringSubmatch(line, -1)
if len(m) != 1 {
return nil, fmt.Errorf("Failed to match first line: %s", line)
}
if len(m[0]) != 6 {
return nil, fmt.Errorf("Got %d matches. Expected 6. Failed to match first line: %s", len(m[0]), line)
}
data := make(map[string]interface{}, 3)
// check for $1 and $2 for the error condition
if m[0][1] != "" && m[0][2] != "" {
data["short_name"] = m[0][1]
data["status"] = strings.ReplaceAll(m[0][2], " ", "_")
data["mounted"] = strconv.FormatBool(false)
return data, nil
}
if m[0][3] != "" && m[0][4] != "" {
data["display_name"] = m[0][3]
data["status"] = strings.ReplaceAll(m[0][4], " ", "_")
data["mounted"] = strconv.FormatBool(m[0][5] != "")
return data, nil
}
return nil, fmt.Errorf("Unknown first line: %s", line)
}